高级查询就三步骤;
query对象作用:拼接sql语句,生成sql的参数列表.用于处理请求.
getPage方法作用:将生成的查询结果封装成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
}
从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();
}
实现于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完对象需要注入值)
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完对象需要注入值)
上述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);