一般而言,我们在实现分页查询XXX列表的功能时,都会创建一个封装分页数据的实体类。这里,我们也不例外,在com.meimeixia.crm.domain包下创建一个这样子的实体类。
package com.meimeixia.crm.domain;
import java.util.List;
public class PageBean<T> {
private Integer currentPage; //当前页数
private Integer pageSize; //每页显示的记录数
private Integer totalCount; //总记录数
private Integer totalPage; //总页数
private List<T> list; //每页查询到的数据的集合,要用到泛型,也即查客户,list里面装的是客户,查联系人,list里面装的是联系人
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
}
然后,我们就要在CustomerAction类中编写一个分页查询客户列表的方法了。在该方法中,需要接收分页查询的参数,这里最好使用离线条件查询对象(即DetachedCriteria对象),因为用了它之后,在我们底层Hibernate模板调用的时候,直接就可以进行分页查询了,而且后期咱们进行条件查询(条件查询还能带分页),使用DetachedCriteria这个对象就会变得非常方便。
package com.meimeixia.crm.web.action;
import org.hibernate.criterion.DetachedCriteria;
import com.meimeixia.crm.domain.Customer;
import com.meimeixia.crm.domain.PageBean;
import com.meimeixia.crm.service.CustomerService;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* 客户管理的Action类
* @author liayun
*
*/
public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
//模型驱动使用的对象
private Customer customer = new Customer();
@Override
public Customer getModel() {
return customer;
}
//注入service
private CustomerService customerService;
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
//使用set方法的方式来接收数据
private Integer currentPage = 1;//手动给其赋值
public void setCurrentPage(Integer currentPage) {
if (currentPage == null) {
currentPage = 1;//给它设置一个默认值,即一开始查看的是第一页的数据
}
this.currentPage = currentPage;
}
//再使用set方法的方式来接收每页显示的记录数
private Integer pageSize = 3;//手动给其赋值
public void setPageSize(Integer pageSize) {
if (pageSize == null) {
pageSize = 3;//给它设置一个默认值,即一开始查看的时候,每页就显示3条记录
}
this.pageSize = pageSize;
}
/*
* 客户管理模块当中的跳转到添加页面的saveUI方法
*/
public String saveUI() {
return "saveUI";
}
/*
* 保存客户的方法
*/
public String save() {
//保存客户
customerService.save(customer);
return NONE;
}
/*
* 分页查询客户列表的方法
*/
public String findAll() {
//需要接收分页查询的参数
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
//在这里还可以在web层来设置条件
//...
//调用业务层去查询
PageBean<Customer> pageBean = customerService.fingByPage(detachedCriteria, currentPage, pageSize);
ActionContext.getContext().getValueStack().push(pageBean);
return "findAll";
}
}
接着,我们还得在Struts2配置文件中(即struts.xml)对CustomerAction进行如下的配置,即配置页面的跳转。
首先,在CustomerService接口中添加一个分页查询客户列表的方法声明,如下:
package com.meimeixia.crm.service;
import org.hibernate.criterion.DetachedCriteria;
import com.meimeixia.crm.domain.Customer;
import com.meimeixia.crm.domain.PageBean;
/**
* 客户管理类的业务层的接口
* @author liayun
*
*/
public interface CustomerService {
void save(Customer customer);
PageBean<Customer> fingByPage(DetachedCriteria detachedCriteria, Integer currentPage, Integer pageSize);
}
然后,在以上接口的一个实现类(CustomerServiceImpl.java)中去实现分页查询客户列表的方法。
package com.meimeixia.crm.service.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.transaction.annotation.Transactional;
import com.meimeixia.crm.dao.CustomerDao;
import com.meimeixia.crm.domain.Customer;
import com.meimeixia.crm.domain.PageBean;
import com.meimeixia.crm.service.CustomerService;
/**
* 客户管理的业务层的实现类
* @author liayun
*
*/
@Transactional
public class CustomerServiceImpl implements CustomerService {
//注入客户的dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
//业务层保存客户的方法
@Override
public void save(Customer customer) {
customerDao.save(customer);
}
//业务层分页查询客户的方法
@Override
public PageBean<Customer> fingByPage(DetachedCriteria detachedCriteria, Integer currentPage, Integer pageSize) {
PageBean<Customer> pageBean = new PageBean<Customer>();
//封装当前的页数
pageBean.setCurrentPage(currentPage);
//封装每页显示的记录数
pageBean.setPageSize(pageSize);
//封装总记录数
//得调用dao来查询
Integer totalCount = customerDao.findCount(detachedCriteria);
pageBean.setTotalCount(totalCount);
//封装总页数
Double tc = totalCount.doubleValue();
Double num = Math.ceil(tc / pageSize);
pageBean.setTotalPage(num.intValue());
//封装每页显示的数据集合
Integer begin = (currentPage - 1) * pageSize;//计算从哪儿开始?
List<Customer> list = customerDao.findByPage(detachedCriteria, begin, pageSize);
pageBean.setList(list);
return pageBean;
}
}
首先,在CustomerDao接口中添加一个统计客户记录数的方法声明和一个分页查询客户列表的方法声明,如下:
package com.meimeixia.crm.dao;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import com.meimeixia.crm.domain.Customer;
/**
* 客户管理的dao的接口
* @author liayun
*
*/
public interface CustomerDao {
void save(Customer customer);
Integer findCount(DetachedCriteria detachedCriteria);
List<Customer> findByPage(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize);
}
然后,在以上接口的一个实现类(CustomerDaoImpl.java)中去实现上面的两个方法。
package com.meimeixia.crm.dao.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.meimeixia.crm.dao.CustomerDao;
import com.meimeixia.crm.domain.Customer;
/**
* 客户管理的dao的实现类
* @author liayun
*
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
//dao中保存客户的方法
@Override
public void save(Customer customer) {
this.getHibernateTemplate().save(customer);
}
//dao中带条件去统计个数的方法
@Override
public Integer findCount(DetachedCriteria detachedCriteria) {
//还得给DetachedCriteria对象设置条件,你要没设置条件,就查询所有了。
//因为我们现在要发送类似select count(*) from xxx where [条件]这样的sql语句
detachedCriteria.setProjection(Projections.rowCount());
List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
if (list.size() > 0) {
return list.get(0).intValue();
}
return null;
}
//dao中分页查询客户的方法
@Override
public List<Customer> findByPage(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize) {
//在查询之前,先要把DetachedCriteria对象中的count那个地方给清空掉,去掉之后,默认就是查所有
detachedCriteria.setProjection(null);
return (List<Customer>) this.getHibernateTemplate().findByCriteria(detachedCriteria, begin, pageSize);
}
}
在编写以上两个方法的时候,一定要特别注意一点,这点我已在下图中着重说明了。
先不要急着去实现页面底部的分页工具条,仅仅是在页面中显示一下查询出来的客户列表数据。
此时,发布我们的项目到Tomcat服务器并启动,然后访问该项目的首页,点击客户列表超链接之后就能显示客户列表了。
可以看到在显示客户对象所关联的数据字典对象时,出现了延迟加载的问题。那怎样解决该问题呢?Spring提供了一个延迟加载问题的解决方案,即使用OpenSessionInViewFilter过滤器来解决延迟加载问题。想要使用这个OpenSessionInViewFilter过滤器,我们还得在web.xml文件配置一把。
再次发布我们的项目到Tomcat服务器并启动,然后访问该项目的首页,点击客户列表超链接之后就能看到正确地显示客户列表了。
下面,我们就来实现页面底部的分页工具条,我觉得写起来真的超麻烦的!这里直接给出页面底部的分页工具条的实现代码。
这样一来,我们以后在实现分页查询XXX列表的功能,显示页面底部的分页工具条时,就能复用以上写的代码了。此时,发布我们的项目到Tomcat服务器并启动,然后访问该项目的首页,点击客户列表超链接之后,你就能进行测试了,应该是好使的!