1,对于分页来说,效率是关键,本例是在分页的时候,缓存5页记录,默认每页20条,缓存大小100,这可以修改的;
2,基本思路是:第一次查的时候,先判断缓存中存不存在当前页的数据,如果存在,查找缓存中的数据,如果不存在,则去数据库中查询5页数据放入缓存中,然后再缓存中读取数据。如果是当前页是前3页,那么读取1-5页的数据,如果当前页是后3页,读取后5页的数据,如果是中间页,读取当前页前两页+当前页+当前页后两页的数据;
一,分页的参数封装类、返回结果封装类;
package com.dg11185.iyw.common;
/**
* 分页的参数类
*
* @author 黄文韬
* @since 1.0
* @Copyright 2013 东莞市邮政局All rights reserved.
*/
public class PagingParams {
private Integer nextPage;// 需要显示内容的页码
private Integer pageSize; // 每页的条数
private String allSizeHql; // 查询总记录条数的hql
private String queryHql; // 查询记录的hql
private Class clazz; //查询对象的class类
//设置下一页的页码
public Integer getNextPage() {
if (nextPage == null || "".equals(nextPage)) {
return 1;
}else {
return nextPage;
}
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
public void setNextPage(Integer nextPage) {
this.nextPage = nextPage;
}
public Integer getPageSize() {
if (pageSize == null || "".equals(pageSize)) {
int configSize = Integer.parseInt(SysConfig.getProperty("pageSize"));
return configSize;
}else {
return pageSize;
}
}
//设置每页条数
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public String getAllSizeHql() {
return allSizeHql;
}
public void setAllSizeHql(String allSizeHql) {
this.allSizeHql = allSizeHql;
}
public String getQueryHql() {
return queryHql;
}
public void setQueryHql(String queryHql) {
this.queryHql = queryHql;
}
}
package com.dg11185.iyw.common;
import java.util.List;
/**
* 分页结果类
*
* @author 黄文韬
* @since 1.0
* @Copyright 2013 东莞市邮政局All rights reserved.
*/
public class PagingResults {
private int currentPage; //当前页码
private int totalSize; //总共条数
private int totalPages; //总共页数
private List list; //结果集
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
二,分页缓存类
package com.dg11185.iyw.common;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.apache.log4j.Logger;
import com.dg11185.iyw.baseDAO.BaseDAOImpl;
/**
* 分页缓存类
* @author hwt
*
*/
public class CachePage {
private static final Logger LOGGER = Logger.getLogger(CachePage.class);
@Resource
private BaseDAOImpl baseDAOImpl;
private int pageStart = 1; // 页码
private int pageSize = 20; // 每页显示的大小
private int pageNum = 0; //总页数
private int totalNum = 0; //总记录条数
//private int cacheSize = 100; // 缓存大小
private List cacheList = new ArrayList(); // 缓存列表
/**
* 构造方法
* @param pageSize 每页大小
* @param cacheSize 缓存大小
*/
public CachePage(Integer pageSize) {
this.pageSize = pageSize;
}
/**
* 判断是否存在缓存中
*
* @param page
* 页码
* @return
*/
public boolean inCache(int page) {
// 当前缓存对象的个数
int cacheNum = cacheList.size();
if (cacheNum > 0) {
if (page <= 0) {
page = 1;
}
// 判断当前页是不是在缓存中
if (page >= pageStart && (page - pageStart) * pageSize <= cacheNum) {
return true;
} else {
return false;
}
}else {
return false;
}
}
/**
* 清空缓存
* @param pageNum 起始页
*/
public void refleshCache() {
// this.isFirst = true;
for (int i = cacheList.size() -1 ; i >= 0; i--) {
cacheList.remove(i);
}
}
/**
* 新增缓存
*
* @param doc
*/
public void addCache(Object obj) {
if (this.cacheList.size() < pageSize*5) {
this.cacheList.add(obj);
} else {
LOGGER.info("缓存池已满");
}
}
/**
* 读缓存中的数据
* @param page
* @return
*/
public PagingResults readCache(int page) {
int start = (page - pageStart) * pageSize;
int end = start + pageSize > cacheList.size() ? cacheList.size()
: start + pageSize;
//缓存中的结果集
List cacheRs = new ArrayList();
for (int i = start; i < end; i++) {
cacheRs.add(cacheList.get(i));
}
//缓存结果集
PagingResults pageResult = new PagingResults();
pageResult.setCurrentPage(page); //当前页
pageResult.setTotalSize(totalNum); //总记录条数
pageResult.setTotalPages(pageNum); //总页数
pageResult.setList(cacheRs);
return pageResult;
}
/**
* 搜索
* @param query query对象
* @param sort 排序对象
* @param page 页码
* @return
*/
public PagingResults search(PagingParams params) throws IOException{
int page = params.getNextPage();
if (page < 0) {
page = 1;
}
//如果存在缓存中
if (inCache(page)) {
return readCache(page);
}else {//如果不在缓存中
//总共记录条数
int totalNum = baseDAOImpl.getSum(params.getAllSizeHql());
//总页数
int pageNum = totalNum % pageSize == 0 ? totalNum / pageSize : totalNum / pageSize + 1;
if (page > pageNum) {
page = pageNum;
}
//保存当前页的前后两页放入缓存中
int startPage = 1;
int endPage = 1;
if (page <= 5) { //前五页
startPage = 1;
endPage = startPage + 4 > pageNum ? pageNum : startPage + 4;
}else if(page >= pageNum - 4){ //后五页
endPage = pageNum ;
startPage = endPage - 4 < 0 ? 1 : endPage - 4;
} else { //中间页
startPage = page - 2 <= 0 ? 1 : page - 2;
endPage = page + 2 > pageNum ? pageNum : page + 2;
}
//清空缓存
refleshCache();
//得到缓存结果集
List resultList = baseDAOImpl.getAllResults(params.getQueryHql(),startPage,pageSize*5,params.getClazz());
//将对象加入缓存中
for (int i = 0,len = resultList.size() ; i < len; i++) {
addCache(resultList.get(i));
}
//替换缓存集合
this.pageNum = pageNum;
this.totalNum = totalNum;
this.pageStart = startPage;
return readCache(page);
}
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getPageStart() {
return pageStart;
}
public void setPageStart(Integer pageStart) {
this.pageStart = pageStart;
}
// public Integer getCacheSize() {
// return cacheSize;
// }
//
// public void setCacheSize(Integer cacheSize) {
// this.cacheSize = cacheSize;
// }
}
三,dao层的两个方法,其他方法省略....
package com.dg11185.iyw.baseDAO;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import com.dg11185.iyw.common.ObjectRowMapper;
import com.dg11185.iyw.common.PagingParams;
/**
* BaseDAO的实现类
*
* @author 黄文韬
* @since 1.0
* @Copyright 2013 东莞市邮政局All rights reserved.
*/
@Repository
public class BaseDAOImpl extends JdbcDaoSupport implements BaseDAO {
@Resource(name = "dataSource")
public void setMyDataSource(DataSource dataSource) {
super.setDataSource(dataSource);
}
/**
* 根据序列得到记录的ID
*
* @param seqName
* @return
*/
@Override
public int getTableId(String seqName) {
String queryId = "select " + seqName + ".nextval from dual";
return getJdbcTemplate().queryForInt(queryId);
}
/**
* 得到所有的记录
*
* @param sql 查询sql
* @param startPage 起始页
* @param pageSize 每页大小
* @param claszz 查询的类名
* @return
*/
public List getAllResults(String sql, Integer startPage, Integer pageSize,
Class claszz) {
// 终止位置
int start = (startPage - 1) * pageSize + 1;
int end = startPage * pageSize;
// 得到分页数据
String allSQL = "select * from(select rownum rn,e.* from (" + sql
+ ") e where rownum <= " + end + ") where rn >= " + start;
List locations = getJdbcTemplate().query(allSQL,
new ObjectRowMapper(claszz));
return locations;
}
/**
* 得到总共的数据
*
* @param sql
* @return
*/
@Override
public int getSum(String sql, Object... obj) {
return getJdbcTemplate().queryForInt(sql, obj);
}
//。。。。(其他方法省略)
}