/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.component.support.persistence.pagequery;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.apache.commons.collections.CollectionUtils;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.persistence.QueryCondition;
import com.jinhe.tss.core.util.BeanUtil;
import com.jinhe.tss.core.util.EasyUtils;
import com.jinhe.tss.core.util.MacrocodeCompiler;
/**
* 分页条件查询基类
*/
public abstract class PaginationQuery {
static final String[] COMMON_IGNORE_PROPERTIES = new String[] { "page", "conditionMacrocodes", "class", "ignoreProperties", "order" };
protected EntityManager em;
protected String ql; // SQL 或 HQL 语句,里面带宏,传入时不带order by
protected MacrocodeQueryCondition condition;
public PaginationQuery(EntityManager em, String ql, MacrocodeQueryCondition condition) {
if ( em == null ) throw new BusinessException("em不能为空");
if ( condition == null ) throw new BusinessException("分页条件查询对象不能为空");
if ( EasyUtils.isNullOrEmpty(ql) ) throw new BusinessException("查询语句不能为空");
this.em = em;
this.ql = ql;
this.condition = condition;
}
/**
* <p>
* 执行分页查询,获取分页结果及相关信息
* </p>
* @return
*/
public PageInfo getResultList() {
Set<String> ignores = condition.getIgnoreProperties();
CollectionUtils.addAll(ignores, COMMON_IGNORE_PROPERTIES);
Map<String, Object> properties = BeanUtil.getProperties(condition, ignores);
// 过滤空参数、无效参数对应的宏代码
Map<String, Object> macrocodes = condition.getConditionMacrocodes();
for ( Iterator<String> it = macrocodes.keySet().iterator(); it.hasNext(); ) {
String key = it.next();
if (key.startsWith("${") && key.endsWith("}")) {
String name = key.substring(2, key.length() - 1);
Object value = properties.get(name);
if ( QueryCondition.isValueNullOrEmpty(value) ) {
it.remove();
}
}
}
// 解析带了宏定义的QL语句
String queryQl = MacrocodeCompiler.run(ql, macrocodes);
PageInfo page = condition.getPage();
page.setTotalRows(getTotalRows(queryQl, properties));
// 获取当前页数据记录集
int firstResult = page.getFirstResult();
if (firstResult >= 0) {
// 添加HQL中order by 语句
appendOrderBy();
Query query = createQuery(queryQl);
query.setFirstResult(firstResult);
query.setMaxResults(page.getPageSize());
// 为查询语句设置相应的参数
setProperties4Query(query, properties);
page.setItems( query.getResultList() );
}
return page;
}
/* 添加HQL中order by 语句 */
private void appendOrderBy(){
if ( condition.getOrderByFields() == null ) return;
String orderByFiledContent = "";
for ( String field : condition.getOrderByFields() ) {
if( EasyUtils.isNullOrEmpty(field) ) continue;
if ( orderByFiledContent.length() > 0 ) {
orderByFiledContent += ", ";
}
orderByFiledContent += field;
}
if ( orderByFiledContent.length() > 0 ) {
ql += " order by " + orderByFiledContent;
}
}
/**
* <p>
* 为查询语句设置相应的参数
* </p>
* @param query 查询
* @param properties 参数集
*/
protected void setProperties4Query(Query query, Map<String, Object> properties) {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
Object value = entry.getValue();
if ( !QueryCondition.isValueNullOrEmpty(value) ) {
query.setParameter( entry.getKey(), value );
}
}
}
/**
* <p>
* 获取总记录数
* </p>
* @param sumQl 统计QL语句
* @param properties 参数集
* @return Integer 总记录数
*/
protected Integer getTotalRows(String ql, Map<String, Object> properties) {
// 生成对应的总记录数统计QL语句
int fromIndex = ql.toLowerCase().indexOf("from ");
int toIndex = ql.toLowerCase().indexOf(" order by ");
if(toIndex <= 0) {
toIndex = ql.length();
}
String sumHql = "select count(*) " + ql.substring(fromIndex, toIndex);
Query query = this.createQuery(sumHql);
setProperties4Query(query, properties);
return EasyUtils.convertObject2Integer(query.getSingleResult());
}
/**
* <p>
* 通过QL语句创建对应的Query对象
* </p>
* @param ql 查询HQL/SQL语句
* @return Query对象
*/
protected abstract Query createQuery(String ql);
}