基本思路:
当一个用户提交的分页查询请求过来时,通常带有请求的页码、过滤条件、排序要求等信息。我们可以在控制层,即在action类相应方法中,把上面的请求信息封闭成一个HQL语句,然后传给业务层的分页查询方法,由分页查询方法返回一个Page对象,这个对象里面就包括了需要在页面中显示的所有内容。
在业务层的分页查询方法中,为了封装一个Page对象,需要查询符合条件的总记录数和当前页的记录,所以在控制层中需要生成两条HQL语句,并且还要传相关的HQL语句参数过来。针对这个需求,我们可以创建一个工具类HqlHelper来负责生成这些HQL语句。
考虑到通用性,我们可以将分页查询方法放在BaseDao接口中。
一、创建HqlHelper工具类
package com.charlie.shop.util;
import java.util.ArrayList;
import java.util.List;
/**
* 这个类负责拼接分页查询的hql语句
* @author charlie
*
*/
public class HqlHelper {
/**查询数据列hql语句**/
private String listHql;
/**查询符合条件的总记录数的HQL语句**/
private String countHql;
/**HQL语句的参数数组**/
private List<Object> parameters = new ArrayList<Object>();
/**条件子句,用于过滤,非必需,所以要初始化为空**/
private String conditionString = "";
/**排序子句,非必需,先初始化为空**/
private String orderString ="";
/**要查询的实体类的类名**/
private String className;
/**要查询的实体类的别名**/
private String alias;
/**
* 构造器
* 有些实体的删除操作并不是物理删除,而只是设置一个visible属性,删除时将该属性设为false,即不可见
* 那么,可以增加一个约定,那就是如果删除时并不想真正物理删除的实体,都给它加上一个visible属性,
* 而在删除时是真正物理删除的实体则不能有这个visible属性
* 如果设置了visible属性,那么在显示列表时,也必须不能显示那些visible=false的对象
* 为了保证这点,可以在HqlHelper构造器中加了一个布尔标志flag
* 当flag=true时,要查询的实体具有visible属性,那么要加上过滤条件
* 当flag=false时,则不用加过滤条件
* @param className 实体类类名
* @param alias 实体类的别名
* @param flag 标志,true时表示实体具有visible属性,false表不具有
*/
public HqlHelper(String className,String alias,boolean flag){
this.className = className;
this.alias = alias;
listHql = "FROM "+className+" "+alias+" ";//注意空格
countHql = "SELECT COUNT(*) FROM "+className+" "+alias+" ";
//如果实体具有visible属性,那么查询的条件必须有visible=true
if(flag){
this.setCondition(alias+".visible=?", true);
}
}
/**
* 设置过滤子句
* @return 返回对象本身,可以实现链式方法调用
*/
public HqlHelper setCondition(String condition,Object...params){
if(conditionString.length()==0){
//条件子句第一次赋值
conditionString=" WHERE "+condition;
}else{
//不是第一次
conditionString +=" AND "+condition;
}
//添加参数对象
for(int i=0;i<params.length;i++){
parameters.add(params[i]);
}
return this;
}
/**
* 设置排序子句
* @param order 字段名
* @param flag 升降序标志,true表升序,false表降序
* @return 返回对象自己,可以实现链式方法调用
*/
public HqlHelper setOrder(String order,boolean flag){
if(orderString.length()==0){
//第一次
orderString = " ORDER BY "+order;
}else{
//不是第一次
orderString += " , "+order;
}
//添加排序方式
if(flag){
//为true,表升序
orderString += " ASC ";
}else{
//降序
orderString += " DESC ";
}
return this;
}
//--------------getter/setter方法----------------------
public String getListHql() {
listHql += " "+conditionString+" "+orderString;
return listHql;
}
public void setListHql(String hql) {
this.listHql = hql;
}
public List<Object> getParameters() {
return parameters;
}
public void setParameters(List<Object> parameters) {
this.parameters = parameters;
}
public String getConditionString() {
return conditionString;
}
public void setConditionString(String conditionString) {
this.conditionString = conditionString;
}
public String getOrderString() {
return orderString;
}
public void setOrderString(String orderString) {
this.orderString = orderString;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getCountHql() {
countHql += " "+conditionString;
return countHql;
}
public void setCountHql(String countHql) {
this.countHql = countHql;
}
}
二、BaseDao接口中添加分页查询方法
/**
* 分页查询方法
*/
public Page<T> getByPage(int pageNow,HqlHelper hqlHelper);
三、在BaseDaoImp类中实现分页查询方法
分三步实现:
1、查询符合条件的总记录数
2、查询符合条件的数据
3、封装到Page对象中,并返回
// 在分页查询中,每一页显示的记录数,默认是10
protected int pageSize = 10;
@Override
public Page<T> getByPage(int pageNow, HqlHelper hqlHelper) {
int maxResults = pageSize;
int firstResult = (pageNow-1)*pageSize;
int recordCount = getRecordCount(hqlHelper.getCountHql(),hqlHelper.getParameters());
List<T> recordList = getPageData(hqlHelper.getListHql(), hqlHelper.getParameters(), firstResult, maxResults);
Page<T> page = new Page<T>(pageNow, pageSize, recordCount, recordList);
return page;
}
/**
* 查询符合条件的总记录数
*/
private int getRecordCount(String countHql,List<Object> params){
Query query = getSession().createQuery(countHql);
for(int i=0;i<params.size();i++){
query.setParameter(i,params.get(i));
}
return Integer.parseInt(query.uniqueResult().toString());
}
/**
* 查询分页数据
*/
private List<T> getPageData(String hql,List<Object> params,int firstResult,int maxResults) {
Query query = getSession().createQuery(hql);
for(int i=0;i<params.size();i++){
query.setParameter(i,params.get(i));
}
query.setFirstResult(firstResult);
query.setMaxResults(maxResults);
return query.list();
}