当前位置: 首页 > 工具软件 > Object Query > 使用案例 >

【Hibernate】【高级查询】【QueryObject+Page+dao.getPage(Query)】

阎雪峰
2023-12-01

高级查询就三步骤;

  1. 将页面请求来的查询数据,封装成一个XXXQuery对象.
  2. 在XXXDAOImpl中,声明方法public Page getPage(Query对象)
  3. Action中,调用方法得到Page对象,并响应.

query对象作用:拼接sql语句,生成sql的参数列表.用于处理请求.
getPage方法作用:将生成的查询结果封装成page对象
page对象作用: 里面是页面内容,包括页码信息,高级查询结果.用于响应.

Page<T>

page对象是页面的封装信息,用于响应给浏览器的对象.那么必须由以下8个信息.
这四个是外界提供的,由构造器传入
1. 总信息条数 ———dao.getPage() 通过Query对象的查总数hql
2. 当前页—————请求放过来的 封装于Query对象
3. 每页信息数 ———请求发过来 封装于Query对象
4. 高级查询结果——-dao.getPage() 通过Query对象查列表的list

这四个是自己生成的,由构造器声明
1. 上一页: ————当前页==1?当前页:当前页-1
2. 尾页—————-总信息条数%每页信息数==0?0:总信息条数/每页信息数+1
3. 下一页 ————-当前页==尾页?尾页:当前页+1
4. 首页 —————-1

public class Page<T> {
    private Integer nextPage;    //下一页
    private Integer prevPage;    //上一页
    private Integer firstPage;   //首页
    private Integer lastPage;    //尾页
    private Integer totalCount;  //总信息条数
    private Integer currentPage; //当前页
    private Integer pageSize;    //每页信息数
    private T  list;             //高级查询结果


    public Page(Integer totalCount, Integer currentPage, Integer pageSize,
            T list) {
        //四个传入
        this.totalCount = totalCount;
        this.currentPage = currentPage;
        this.pageSize = pageSize;
        this.list = list;
        //四个声明
        this.firstPage=1;
        this.lastPage=totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
        this.nextPage=currentPage==lastPage?lastPage:currentPage+1;
        this.prevPage=currentPage==firstPage?firstPage:currentPage-1;

    }
    //省略setter getter toString
}

Query类

1.制定规范:IQuery

从Page类中,得知需要四个形参才可以创建page对象
Query要做的是提供六个参数给dao:
1.提供当前页currentPage.
2.提供每页信息数pageSize.
3.提供查询列表的条件hql:listHQL
4.提供查询列表的条件hql的参数列表:listParameters
5.提供查询总数的条件hql:countHQL
6.提供查询总数的条件hql的参数列表:countParameters

public interface IQuery {
    public String        getCountHQL();
    public String        getListHQL();
    public List<Object>  getCountParameters();
    public List<Object>  getListParameters();
    public Integer       getCurrentPage();
    public Integer       getPageSize();
}

2.QueryObject

实现于IQuery,是XXXQuery的父类.

public abstract class QueryObject implements IQuery{
    //声明和初始化六个参数
    private Integer        pageSize=3;
    private Integer        currentPage=1;
    private StringBuilder  listHQL=new StringBuilder(100);
    private StringBuilder  countHQL=new StringBuilder(100);
    private List<Object>   countParameters=new ArrayList<>();
    private List<Object>   listParameters =new ArrayList<>();

    //两个布尔类型用于判断hql和参数list是否初始化
    private boolean        listInit=false;
    private boolean        countInit=false;


    //实现接口方法  返回hql和其参数列表时候,要判断是否已经初始化过.
    public String getCountHQL() {
        if(this.countInit==false) {
            this.setCountHQL();
            countInit=true;
        }
        return this.countHQL.toString();
    }

    public String getListHQL() {
        if(this.listInit==false) {
            this.setListHQL();
            listInit=true;
        }
        return this.listHQL.toString();
    }

    public List<Object> getCountParameters() {
        if(this.countInit==false) {
            this.setCountHQL();
            countInit=true;
        }
        return this.countParameters;
    }

    public List<Object> getListParameters() {
        if(this.listInit==false) {
            this.setListHQL();
            listInit=true;
        }
        return this.listParameters;
    }

    public Integer getCurrentPage() {
        return this.currentPage;
    }

    public Integer getPageSize() {
        return this.pageSize;
    }


    //给子类覆盖的方法  初始化hql和其参数
     protected void setCountHQL(){};
     protected void setListHQL(){};
    //给子类使用的方法 子类自需要传递hql的条件语句和语句对应的参数即可
    protected void setListCondition(String str,Object...obj) {
            this.listHQL.append(str);
            if(obj!=null) {this.listParameters.addAll(Arrays.asList(obj));
    }}
    protected void setCountCondition(String str,Object...obj) {
            this.countHQL.append(str);
            if(obj!=null) {this.countParameters.addAll(Arrays.asList(obj));
    }}
}


    //当前页和每页信息数的set方法.(new完对象需要注入值)

3.EmployeeQuery(拼接条件语和其参数列表)

1.覆盖父类的两个方法,在方法内使用setListCondition(条件语,参数)和setCountCondition(条件语,参数);
2.不拼主体的hql,只拼接条件语句的hql (原因,方便泛型dao,比如查询员工,不需要高级查询时候,就不需要建该类,直接用QueryObject即可,所以主体hql不能放在XXXObject中.)
主体:【 select e from Employee 】在dao或QueryObject中拼
条件语:【where (id = ?) and (name like ? or Email like ?) order by id asc】
3.EmployeeQuery对象是用请求发来的参数创建的

public class EmployeeQueryObject extends QueryObject{
    //高级查询的内容
    private String key;
    private Long id;

    //完成总数hql和其参数列表的方法
    protected void setCountHQL() {
        super.setCountCondition(" where 1=1 ");
        if(StringUtils.hasLength(key)) {super.setCountCondition(" and ( id=? )", id);}
        if(StringUtils.hasLength(key)) {super.setCountCondition(" and (name like ? or Email like ?)", "%"+key+"%", "%"+key+"%");
    }}

    //完成查询列表hql和其参数列表的方法
    protected void setListHQL() {
        super.setListCondition(" where 1=1 ");
        if(StringUtils.hasLength(key)) {super.setCountCondition(" and ( id=? )", id);}
        if(StringUtils.hasLength(key)) {super.setListCondition(" and (name like ? or Email like ?)", "%"+key+"%", "%"+key+"%");}
        super.setListCondition(" order by id ");
    }
}

    //key+id的setter(new完对象需要注入值)

dao.getPage(IQuery q)方法

上述Query对象已经提供了6个参数
- 提供当前页currentPage.
- 提供每页信息数pageSize.
- 提供查询列表的条件hql:listHQL
- 提供查询列表的条件hql的参数列表:listParameters
- 提供查询总数的条件hql:countHQL
- 提供查询总数的条件hql的参数列表:countParameters

getPage(Query q)方法中要做的事情:
1. 完善查列表hql , 查总数的hql:主体(自己写)+条件语(q对象获取),发送这两条hql,分别获得 list 和 totalCount;
2. 获得当前页和每页信息数 currentPage,pageSize
3. 通过构造方法生成Page对象


public class EmployeeDAOImpl implements IEmployeeDAO{
     public Page<List<Employee>> getPage(IQuery q) {
        Session session = sessionFactory.getCurrentSession();
        //获取currentPage
        Integer currentPage = q.getCurrentPage();

        //获取pageSize
        Integer pageSize = q.getPageSize();

        //获取totalCount
        String countHQL ="select count(e) from Employee e "+ q.getCountHQL();
        Query countQuery = session.createQuery(countHQL);
        this.setParamter(countQuery, q.getCountParameters());
        int  totalCount= ((Long)countQuery.list().get(0)).intValue();

        //获取list+分页 limit by (currentPage-1)*pageSize), pageSize 
        String listHQL="select e from Employee e "+q.getListHQL();
        Query listQuery = session.createQuery(listHQL);
        this.setParamter(listQuery, q.getListParameters());
        List<T> list = listQuery
                                .setFirstResult((currentPage-1)*pageSize)
                                .setProperties(pageSize).list();

        return new Page<List<Employee>>(totalCount, currentPage, pageSize, list);
    }
}


    //循环设置参数
    private void setParamter(Query query,List<Object> list) {
        for (int i=0;i<list.size();i++) {
            query.setParameter(i, list.get(i));

        }
    }

使用

//员工查询需要高级查询
EmployeeQuery q=new EmployeeQuery();
q.setXXX(XX);//设置各种参数(当前页,每页条数+高级查询信息)
Page page=employeeDAO.getPage(q);
//部门查询需要不需要高级查询 ,省去创建DeparementQuery类
QueryObject q=new QueryObject();
q.setXXX(XX);//当前页,每页条数
Page page=employeeDAO.getPage(q);

总结

  1. 条件语句+排序方式:在XXXQuery中拼接
  2. 主体hql: 在dao或QueryObject拼接
  3. 分页hql: 在dao.getPage()中调用方法设置.
 类似资料: