ibatis支持hibernate式的物理分页

ibatis支持hibernate式的物理分页
ibatis支持hibernate式的物理分页

对IBatis分页的改进,使ibatis支持hibernate式的物理分页

一直以来ibatis的分页都是通过滚动ResultSet实现的,应该算是逻辑分页吧。逻辑分页虽然能很干净地独立于特定数据库,但效率在多数情况下不及特定数据库支持的物理分页,而hibernate的分页则是直接组装sql,充分利用了特定数据库的分页机制,效率相对较高。本文讲述的就是如何在不重新编译ibatis源码的前提下,为ibatis引入hibernate式的物理分页机制。

基本思路就是找到ibatis执行sql的地方,截获sql并重新组装sql。通过分析ibatis源码知道,最终负责执行sql的类是

com.ibatis.sqlmap.engine.execution.SqlExecutor,此类没有实现任何接口,这多少有点遗憾,因为接口是相对稳定契约,非大的版本更新,接口一般是不会变的,而类就相对易变一些,所以这里的代码只能保证对当前版本(2.1.7)的ibatis有效。下面是 SqlExecutor执行查询的方法:

Java代码

1./**

2. * Long form of the method to execute a query

3. *

4. * @param request - the request scope

5. * @param conn - the database connection

6. * @param sql - the SQL statement to execute

7. * @param parameters - the parameters for the statement

8. * @param skipResults - the number of results to skip

9. * @param maxResults - the maximum number of results to retur

n

10. * @param callback - the row handler for the query

11. *

12. * @throws SQLException - if the query fails

13. */

14. public void executeQuery(RequestScope request, Connection con

n, String sql, Object[] parameters,

15. int skipResults, int maxResults, Row

HandlerCallback callback)

16. throws SQLException {

17. ErrorContext errorContext = request.getErrorContext();

18. errorContext.setActivity("executing query");

19. errorContext.setObjectId(sql);

20.

21. PreparedStatement ps = null;

22. ResultSet rs = null;

23.

24. try {

25. errorContext.setMoreInfo("Check the SQL Statement (prepar

ation failed).");

26.

27. Integer rsType = request.getStatement().getResultSetType(

);

28. if (rsType != null) {

29. ps = conn.prepareStatement(sql, rsType.intValue(), Resu

ltSet.CONCUR_READ_ONLY);

30. } else {

31. ps = conn.prepareStatement(sql);

32. }

33.

34. Integer fetchSize = request.getStatement().getFetchSize()

;

35. if (fetchSize != null) {

36. ps.setFetchSize(fetchSize.intValue());

37. }

38.

39. errorContext.setMoreInfo("Check the parameters (set param

eters failed).");

40. request.getParameterMap().setParameters(request, ps, para

meters);

41.

42. errorContext.setMoreInfo("Check the statement (query fail

ed).");

43.

44. ps.execute();

45. rs = getFirstResultSet(ps);

46.

47. if (rs != null) {

48. errorContext.setMoreInfo("Check the results (failed to

retrieve results).");

49. handleResults(request, rs, skipResults, maxResults, cal

lback);

50. }

51.

52. // clear out remaining results

53. while (ps.getMoreResults());

54.

55. } finally {

56. try {

57. closeResultSet(rs);

58. } finally {

59. closeStatement(ps);

60. }

61. }

62.

63. }

其中handleResults(request, rs, skipResults, maxResults, callback)一句用于处理分页,其实此时查询已经执行完毕,可以不必关心handleResults方法,但为清楚起见,下面来看看 handleResults的实现:

Java代码

1.private void handleResults(RequestScope request, ResultSet rs,

int skipResults, int maxResults, RowHandlerCallback callback) t

hrows SQLException {

2. try {

3. request.setResultSet(rs);

4. ResultMap resultMap = request.getResultMap();

5. if (resultMap != null) {

6. // Skip Results

7. if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {

8. if (skipResults > 0) {

9. rs.absolute(skipResults);

10. }

11. } else {

12. for (int i = 0; i < skipResults; i++) {

13. if (!rs.next()) {

14. break;

15. }

16. }

17. }

18.

19. // Get Results

20. int resultsFetched = 0;

21. while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS ||

resultsFetched < maxResults) && rs.next()) {

22. Object[] columnValues = resultMap.resolveSubMap(reque

st, rs).getResults(request, rs);

23. callback.handleResultObject(request, columnValues, rs

);

24. resultsFetched++;

25. }

26. }

27. } finally {

28. request.setResultSet(null);

29. }

30. }

此处优先使用的是ResultSet的absolute方法定位记录,是否支持absolute 取决于具体数据库驱动,但一般当前版本的数据库都支持该方法,如果不支持则逐条跳过前面的记录。由此可以看出如果数据库支持absolute,则ibatis内置的分页策略与特定数据库的物理分页效率差距就在于物理分页查询与不分页查询在数据库中的执行效率的差距了。因为查询执行后读取数据前数据库并未把结果全部返回到内存,所以本身在存储占用上应该差距不大,如果都使用索引,估计执行速度也差不太多。

继续我们的话题。其实只要在executeQuery执行前组装sql,然后将其传给executeQuery,并告诉handleResults我们不需要逻辑分页即可。拦截executeQuery可以采用aop动态实现,也可直接继承SqlExecutor覆盖executeQuery来静态地实现,相比之下后者要简单许多,而且由于SqlExecutor 没有实现任何接口,比较易变,动态拦截反到增加了维护的工作量,所以我们下面来覆盖executeQuery:

Java代码

1.package com.aladdin.dao.ibatis.ext;

2.

3.import java.sql.Connection;

4.import java.sql.SQLException;

5.

6.import https://www.360docs.net/doc/554522740.html,mons.logging.Log;

7.import https://www.360docs.net/doc/554522740.html,mons.logging.LogFactory;

8.

9.import com.aladdin.dao.dialect.Dialect;

10.import com.ibatis.sqlmap.engine.execution.SqlExecutor;

11.import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCal

lback;

12.import com.ibatis.sqlmap.engine.scope.RequestScope;

13.

14.public class LimitSqlExecutor extends SqlExecutor {

15.

16. private static final Log logger = LogFactory.getLog(LimitSq

lExecutor.class);

17.

18. private Dialect dialect;

19.

20. private boolean enableLimit = true;

21.

22. public Dialect getDialect() {

23. return dialect;

24. }

25.

26. public void setDialect(Dialect dialect) {

27. this.dialect = dialect;

28. }

29.

30. public boolean isEnableLimit() {

31. return enableLimit;

32. }

33.

34. public void setEnableLimit(boolean enableLimit) {

35. this.enableLimit = enableLimit;

36. }

37.

38. @Override

39. public void executeQuery(RequestScope request, Connection c

onn, String sql,

40. Object[] parameters, int skipResults, int maxResult

s,

41. RowHandlerCallback callback) throws SQLException {

42. if ((skipResults != NO_SKIPPED_RESULTS || maxResults !=

NO_MAXIMUM_RESULTS)

43. && supportsLimit()) {

44. sql = dialect.getLimitString(sql, skipResults, maxR

esults);

45. if(logger.isDebugEnabled()){

46. logger.debug(sql);

47. }

48. skipResults = NO_SKIPPED_RESULTS;

49. maxResults = NO_MAXIMUM_RESULTS;

50. }

51. super.executeQuery(request, conn, sql, parameters, skip

Results,

52. maxResults, callback);

53. }

54.

55. public boolean supportsLimit() {

56. if (enableLimit && dialect != null) {

57. return dialect.supportsLimit();

58. }

59. return false;

60. }

61.

62.}

其中:

Java代码

1.skipResults = NO_SKIPPED_RESULTS;

2.maxResults = NO_MAXIMUM_RESULTS;

告诉handleResults不分页(我们组装的sql已经使查询结果是分页后的结果了),此处引入了类似hibenate中的数据库方言接口Dialect,其代码如下:

Java代码

1.package com.aladdin.dao.dialect;

2.

3.public interface Dialect {

4.

5. public boolean supportsLimit();

6.

7. public String getLimitString(String sql, boolean hasOffset)

;

8.

9. public String getLimitString(String sql, int offset, int li

mit);

10.}

下面为Dialect接口的MySQL实现:

Java代码

1.package com.aladdin.dao.dialect;

2.

3.public class MySQLDialect implements Dialect {

4.

5. protected static final String SQL_END_DELIMITER = ";";

6.

7. public String getLimitString(String sql, boolean hasOffset)

{

8. return new StringBuffer(sql.length() + 20).append(trim(

sql)).append(

9. hasOffset ? " limit ?,?" : " limit ?")

10. .append(SQL_END_DELIMITER).toString();

11. }

12.

13. public String getLimitString(String sql, int offset, int li

mit) {

14. sql = trim(sql);

15. StringBuffer sb = new StringBuffer(sql.length() + 20);

16. sb.append(sql);

17. if (offset > 0) {

18. sb.append(" limit ").append(offset).append(',').app

end(limit)

19. .append(SQL_END_DELIMITER);

20. } else {

21. sb.append(" limit ").append(limit).append(SQL_END_D

ELIMITER);

22. }

23. return sb.toString();

24. }

25.

26. public boolean supportsLimit() {

27. return true;

28. }

29.

30. private String trim(String sql) {

31. sql = sql.trim();

32. if (sql.endsWith(SQL_END_DELIMITER)) {

33. sql = sql.substring(0, sql.length() - 1

34. - SQL_END_DELIMITER.length());

35. }

36. return sql;

37. }

38.

39.}

接下来的工作就是把LimitSqlExecutor注入ibatis中。我们是通过spring 来使用ibatis的,所以在我们的dao基类中执行注入,代码如下:

Java代码

1.package com.aladdin.dao.ibatis;

2.

3.import java.io.Serializable;

4.import java.util.List;

5.

6.import org.springframework.orm.ObjectRetrievalFailureException;

7.import org.springframework.orm.ibatis.support.SqlMapClientDaoSu

pport;

8.

9.import com.aladdin.dao.ibatis.ext.LimitSqlExecutor;

10.import com.aladdin.domain.BaseObject;

11.import com.aladdin.util.ReflectUtil;

12.import com.ibatis.sqlmap.client.SqlMapClient;

13.import com.ibatis.sqlmap.engine.execution.SqlExecutor;

14.import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;

15.

16.public abstract class BaseDaoiBatis extends SqlMapClientDaoSupp

ort {

17.

18. private SqlExecutor sqlExecutor;

19.

20. public SqlExecutor getSqlExecutor() {

21. return sqlExecutor;

22. }

23.

24. public void setSqlExecutor(SqlExecutor sqlExecutor) {

25. this.sqlExecutor = sqlExecutor;

26. }

27.

28. public void setEnableLimit(boolean enableLimit) {

29. if (sqlExecutor instanceof LimitSqlExecutor) {

30. ((LimitSqlExecutor) sqlExecutor).setEnableLimit(ena

bleLimit);

31. }

32. }

33.

34. public void initialize() throws Exception {

35. if (sqlExecutor != null) {

36. SqlMapClient sqlMapClient = getSqlMapClientTemplate

()

37. .getSqlMapClient();

38. if (sqlMapClient instanceof ExtendedSqlMapClient) {

39. ReflectUtil.setFieldValue(((ExtendedSqlMapClien

t) sqlMapClient)

40. .getDelegate(), "sqlExecutor", SqlExecu

tor.class,

41. sqlExecutor);

42. }

43. }

44. }

45.

46. ...

47.

48.}

其中的initialize方法执行注入,稍后会看到此方法在spring Beans 配置中指定为init-method。由于sqlExecutor是

com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient的私有成员,且没有公开的set方法,所以此处通过反射绕过java的访问控制,下面是ReflectUtil 的实现代码:

Java代码

1.package com.aladdin.util;

2.

3.import https://www.360docs.net/doc/554522740.html,ng.reflect.Field;

4.import https://www.360docs.net/doc/554522740.html,ng.reflect.Method;

5.import https://www.360docs.net/doc/554522740.html,ng.reflect.Modifier;

6.

7.import https://www.360docs.net/doc/554522740.html,mons.logging.Log;

8.import https://www.360docs.net/doc/554522740.html,mons.logging.LogFactory;

9.

10.public class ReflectUtil {

11.

12. private static final Log logger = LogFactory.getLog(Reflect

Util.class);

13.

14. public static void setFieldValue(Object target, String fnam

e, Class ftype,

15. Object fvalue) {

16. if (target == null

17. || fname == null

18. || "".equals(fname)

19. || (fvalue != null && !ftype.isAssignableFrom(f

value.getClass()))) {

20. return;

21. }

22. Class clazz = target.getClass();

23. try {

24. Method method = clazz.getDeclaredMethod("set"

25. + Character.toUpperCase(fname.charAt(0))

26. + fname.substring(1), ftype);

27. if (!Modifier.isPublic(method.getModifiers())) {

28. method.setAccessible(true);

29. }

30. method.invoke(target, fvalue);

31.

32. } catch (Exception me) {

33. if (logger.isDebugEnabled()) {

34. logger.debug(me);

35. }

36. try {

37. Field field = clazz.getDeclaredField(fname);

38. if (!Modifier.isPublic(field.getModifiers())) {

39. field.setAccessible(true);

40. }

41. field.set(target, fvalue);

42. } catch (Exception fe) {

43. if (logger.isDebugEnabled()) {

44. logger.debug(fe);

45. }

46. }

47. }

48. }

49.}

到此剩下的就是通过Spring将sqlExecutor注入BaseDaoiBatis中了,下面是Spring Beans配置文件:

Xml代码

1.

2.

3. "https://www.360docs.net/doc/554522740.html,/dtd/spring-beans.dtd">

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16. classpath:/com/aladdin/dao/ibatis/sql-map-co

nfig.xml

17.

18.

19.

20.

21.

22.

23.

24.

25.

/>

26.

27.

28.

29.

30.

31.

32.

33.

34.

35.

36.

37.

38.

39.

40.

41.

42.

43.

44.

45.

46.

47.

此后就可以通过调用

org.springframework.orm.ibatis.SqlMapClientTemplate的

public List queryForList(final String statementName, final Object parameterObject, final int skipResults, final int maxResults) throws DataAccessException

public PaginatedList queryForPaginatedList(final String statementName, final Object parameterObject, final int pageSize) throws DataAccessException

得到分页结果了。建议使用第一个方法,第二个方法返回的是PaginatedList,虽然使用简单,但是其获得指定页的数据是跨过我们的dao直接访问ibatis的,不方便统一管理。

VS2010+自带分页实现及操作

VS2010 自带分页实现及操作 这里以一个简单的签到系统为例子进行讲解。 先看一下,假设你已经设计好的初始页面,其中填写原因是对点击此条记录进行修改。 图1-1 上图中可以看到已经设置了分页,分页具体设置如下:选择gridview的属性,开启自动分页。 图1-2

然后在gridview的事件里选择分页的事件:如图1-3,可以直接双击就可以。 图1-3

点击填写原因就是报错,下标越界的提示。

这样就解决了第二页下标越界的问题了。 最后遗留的问题是:填写了迟到原因返回后要去到达修改前的那一页。 1.我首先可以在点击填写原因的时候获得当前页的索引int iPageIndex = gvAttend.PageIndex; //获取当前页的索引 2.然后把此ipageIndex一起传到修改页面去。 String URLString= String.Format("FillReason.aspx?WorkDate={0}&CardId={1}&AttendTime={2}&LateReason={ 3}&iPageIndex={4}", WorkDate, cardid, AttendTime, LateReason, iPageIndex); 3.得到修改后以后,再把此ipageIndex传回的修改前的页面。当前页接收 此ipageIndex后,赋值个gridview的pageindex。 int pageindex = Convert.ToInt32(Request.QueryString["pageindex"]); gvAttend.PageIndex=pageindex; 以上所有操作就完成了,vs2010自带分页及操作的功能。

分页的实现步骤

为什么需要分页? 1.从客户角度来讲,数据内容过多,查看数据非常不便。 2.从服务器和网络的角度来讲,查这么多数据,传输这么多数据,是一种效率很低的做法。分页的核心SQL: 最简单最原始的分页: 分页的简单过程: 用户点击第一页传递一个参数:Num=1到后台,服务器获取num=1将该参数传到Dao 中,dao中:select * from tb_article where id>10 limit ?,?;, ps.setint((num-1)*10),返回一个List,传递到jsp中进行显示,发送给客户端。 1.

2.

3.访问:channel.jsp,然后点击在下面的页号导航即可看到简单的分页效果。 首页上一页1,2,3,4,5,6,7,8,9,10 下一页末页共101页 分页的实现原理: 1.获得需要显示的总的记录数rowCount—》从数据库中取 2.设定每页最多显示的记录数size—》10 3.指定显示的页码:num →作为参数得到 4.所要显示的数据对象→根据startRow和size从数据库中查出! 5.根据rowCount,size,num可计算出其余的元素: a)本页面从第几个记录开始:startRow = (this.num-1) * size; b)共有多少页:pageCount = (int) Math.ceil((double)rowCount/size); c)list:包含了所要显示的数据对象的集合 d)下一页:next=Math.min( this.pageCount, this.num+1) e)上一页:prev = Math.max(1 , this.num-1) f)页号控制元素: numCount:每页最多显示多少页号。(一共显示numCount+1个页号) start = Math.max(this.num-numCount/2, first); //本页显示页号从多少页开始 end = Math.min(start+numCount, last); //本页显示页号在多少页结束 页号控制: if(end-start < numCount){ //当本页总显示的页号数不够numCount时,如何计算起始页号。 start = Math.max(end-numCount, 1); } 分页实现步骤 Pagenation工具类代码:

MyBatis自动分页实现

MyBatis自动分页实现 2013-08-16 近两天一直再研究MyBatis的分页问题,看了别人的处理方式,自己总结优化了一下,写了两个拦截类,给有需要的人使用和参考,源码请下载附件。 主要有3个类:Page,MybatisPageInterceptor,MybatisSpringPageInterceptor Page:作为分页对象,有:pageNo、pageSize、totalRecord、totalPage、results属性 MybatisPageInterceptor和MybatisSpringPageInterceptor: 均为拦截类,仅需要选用其中的一个,前者在任何情况下都可用,后再仅在Spring环境下使用。 推荐使用后者,其优点是使用后无需对mapper的XML文件作任何修改,只需要修改Mapper 类的方法,增加一个Page类型的参数即可。而前者使用时有可能会需要修改XML,特别是原Mapper方法只有一个参数时,需要增加@Param指定参数名,而后修改XML文件使用该参数名。 以下给出在Spring环境下的配置使用方法示例: MybatisSpringPageInterceptor: 修改Spring配置文件 Java代码 1. 2. 3. 4. 5.

分页的实现原理,分页的实现步骤

分页的实现原理: 1.获得需要显示的总的记录数rowCount—》从数据库中取 2.设定每页最多显示的记录数size—》10 3.指定显示的页码:num 作为参数得到 4.根据rowCount,size,num可计算出其余的元素: a)本页面从多少行记录开始:startRow = (this.num-1) * size ; b)共有多少页:pageCount = (int) Math.ceil((double)rowCount/size); c)下一页:next=Math.min( this.pageCount, this.num+1) d)上一页:prev = Math.max(1 , this.num-1) e)页号控制元素: numCount:每页最多显示多少页号。(一共显示numCount+1个页号) start = Math.max(this.num-numCount/2, first); //本页显示页号从多少页开始 end = Math.min(start+numCount, last); //本页显示页号在多少页结束 页号控制: if(end-start < numCount){ //当本页总显示的页号数不够numCount时,如何计算起始页号。 start = Math.max(end-numCount, 1); } 分页实现步骤: 1.将Page类引入。需要自己修改的可自行修改。 package com.puckasoft.video.util; public class Page { private int num; //当前页号, 采用自然数计数 1,2,3,... private int size; //页面大小:一个页面显示多少个数据 private int rowCount;//数据总数:一共有多少个数据 private int pageCount; // 页面总数 private int startRow;//当前页面开始行, 第一行是0行 private int first = 1;//第一页页号 private int last;//最后页页号 private int next;//下一页页号 private int prev;//前页页号 private int start;//页号式导航, 起始页号 private int end;//页号式导航, 结束页号 private int numCount = 10;//页号式导航, 最多显示页号数量为numCount+1;这里显示11页。 public Page(int size, String str_num, int rowCount) { int num = 1; if (str_num != null) { num = Integer.parseInt(str_num);

基本分页存储管理的模拟实现

基本分页存储管理的模拟实现 学院 专业 学号 学生姓名 指导教师姓名 2014年03月18日 目录

一、设计目的与内容 二、各个功能模块 三、主要功能模块流程图 四、系统测试 五、结论 六、源程序及系统文件使用说明 一、设计目的与内容 设计的目的: 操作系统课程设计是计算机专业重要的教学环节, 它为学生提供了一个既动手又动脑, 将课本上的理论知识和实际有机的结合起来, 独立分析和解决实际问题的机会。 1. 进一步巩固和复习操作系统的基础知识。 2. 培养学生结构化程序、模块化程序设计的方法和能力。 3. 提高学生调试程序的技巧和软件设计的能力。 4. 提高学生分析问题、解决问题以及综合利用C 语言进行程序设计的能力。 设计内容: 根据设计要求实现对基本分页存储管理的模拟 设计要求:

1. 2. 进程名, 进程所需页数, 也 可从文件读出。 3. 况。 所采用的数据结构: typedef struct LNode{ int f; //进程号 char name[8]; //进程名 int size; //进程大小 int n; //进程页数 int ye[100]; //页表,下标表示页号, 内容表示进程各页所在物理块 struct LNode *next; }LNode,*LinkList; 二、各个功能模块 主要功能模块流程图

四、系统测试 主界面: (显示程序的各个功能块)1、选择1, 运行界面如下:

(选择1, 输入进程名, 显示内存物理块分配情况) 2、选择2, 运行界面如下: (显示2回收进程, 若进程名输入错误, 则显示进程不存在, )3、选择3, 运行界面如下:

php实现简单的分页功能

大家在浏览网页的时候,都会看到每篇文章都会会显示“上一页”“下一页”。下面跟大家分享一下如何用php实现简单的分页功能。 首先,先创建一个mysql表: SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `test` -- ---------------------------- DROP TABLE IF EXISTS `test`; CREATE TABLE `test` ( `id` int(5) NOT NULL AUTO_INCREMENT, `name` varchar(50) CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; 然后在里面插入数据: -- ---------------------------- -- Records of test -- ---------------------------- INSERT INTO `test` VALUES ('1', '张三'); INSERT INTO `test` VALUES ('2', '李四'); INSERT INTO `test` VALUES ('3', '王五'); INSERT INTO `test` VALUES ('4', '赵六');

INSERT INTO `test` VALUES ('5', '阿萨达'); INSERT INTO `test` VALUES ('6', '回火'); INSERT INTO `test` VALUES ('7', 'adada'); 然后新建一个php文件,连接数据库: header("content-type:text/html;charset=UTF-8");//防止页面乱码$link = mysql_connect("localhost","root","") or die("数据库连接失败"); $result = mysql_select_db("test",$link); mysql_query("SET NAMES 'utf8'");//设置数据库连接编码 然后调取数据,并且计算出该表里面总共有多少条数据: function selectdata(){ $sql = "SELECT name FROM `test` ORDER BY id desc"; $arr = array(); $result = mysql_query($sql); while ($array = mysql_fetch_row($result)) { $arr[] = $array; } return $arr; } function selectdatabypages($limit1,$limit2){ $sql = "SELECT name FROM `test` ORDER BY id desc LIMIT $limit1,$limit2";

Java分页查询操作的两种实现办法

Dao实现类 public Listpage(int start, int end) { String pagesql = "select * from (select id,name,price,descri,rownumrn from t_product)where rn between ? and ?"; List list = new ArrayList(); Product p = null; Connection conn = null; PreparedStatementstm = null; ResultSetrs = null; try { conn = JDBCUtil.getConnection(); stm = conn.prepareStatement(pagesql); stm.setInt(1, start); stm.setInt(2, end); rs = stm.executeQuery(); while (rs.next()) { p = new Product(rs.getInt(1), rs.getString(2), rs.getDouble(3), rs.getString(4)); list.add(p); } } catch (Exception e) { thrownew RuntimeException("查询page全部异常", e); } finally { JDBCUtil.close(rs, stm, null); } return list; } public Long count() { Connection conn = null; PreparedStatementstm = null; ResultSetrs = null; Long count = null; try { conn = JDBCUtil.getConnection(); stm = conn.prepareStatement("select count(*) from t_product"); rs = stm.executeQuery(); while (rs.next()) { count = rs.getLong(1); } } catch (Exception e) { thrownew RuntimeException("查询count", e); } finally { JDBCUtil.close(rs, stm, null); } return count; } Service实现类

后台实现JSON分页显示

Action: /** * 团单明细--团体投保信息 */ public String teamInsure() { //String grpcode = getRequestParameter("grpcode"); // 团体代码 String grpcode = "CHS000G01944"; https://www.360docs.net/doc/554522740.html,("grpcode:"+grpcode+"团体投保信息---"); List teamInsureList = new ArrayList(); Pager pager = getPager("classDetailInfo/classDetailInfo_teamInsure.do?page="); pager.setPagesize(3); PageText pageText = null; try { teamInsureList = classDetailInfoServices.getTeamInsure(grpcode); pageText = classDetailInfoServices.getPageText(teamInsureList, pager, teamInsureList.size()); JSONArray jsonArray = new JSONArray(); JSONObject jsonObject = new JSONObject(); for (int i = 0; i < teamInsureList.size(); i++) { jsonObject.element("gappno", (teamInsureList.get(i)).getGappno()); jsonObject.element("gpolicyno", (teamInsureList.get(i)).getGpolicyno()); jsonObject.element("classcode", (teamInsureList.get(i)).getClasscode()); jsonObject.element("size", (teamInsureList.size())); jsonObject.element("pagecount", ((teamInsureList.size() + 2) / 3)); String classcode = (teamInsureList.get(i)).getClasscode(); if (!FunctionUtils.isBlank(classcode)) { String classname = classDetailInfoServices.getClassname(classcode); // 险种名称 jsonObject.element("classname", classname); }else { jsonObject.element("classname", ""); } jsonObject.element("polist", (teamInsureList.get(i)).getPolist()); jsonObject.element("stat", (teamInsureList.get(i)).getStat()); jsonObject.element("sumamt", (teamInsureList.get(i)).getSumamt()); jsonObject.element("illamt", (teamInsureList.get(i)).getIllamt()); jsonObject.element("accamt", (teamInsureList.get(i)).getAccamt()); jsonObject.element("sickamt", (teamInsureList.get(i)).getSickamt()); jsonObject.element("medamt", (teamInsureList.get(i)).getMedamt());

java分页原理及实现方式

Java分页原理及常用分页方法 什么是分页技术 分页,是一种将所有数据分段展示给用户的技术.用户每次看到的不是全部数据,而是其中的一部分。如果在其中没有找到自习自己想要的内容,用户可以通过制定页码或是翻页的方式转换可见内容,直到找到自己想要的内容为止.其实这和我们阅读书籍很类似,我们不能把整本书的全部内容写在一页纸上。 为什么要分页? 1、加载少量数据,减少客户的和服务器数据交互,降低服务器压力。 2、增强用户体验,每次加载数据量少,加载速度自然就快,用户体验就好。 常见分页样式: 1、传统分页(分页工具栏),如百度的分页: 2、自动加载:如QQ空间下拉自动加载数据

传统分页与下拉式分页对比 传统分页可以明确数据信息,数量等; 下拉式无法明确数据量等信息,分页后之前从信息还在页面上。 常见分页实现方式 1.Java程序分页的实现主要是用List接口中的subList(intstartIndex,intendIndex)方法, 这种方式也称为程序内存分页。 2.使用数据库的SQL语句实现数据分页。适用于数据量较大,访问频度较低的操作。如 果数据量大,访问频度又高,可以参考大数据分页。 关于内存分页 当数据量较小时推荐使用。使用subList进行分页时,如果数据量比较大是一个非常耗费系统资源的方案。 目前web项目有许多分布式系统,可能有多个系统访问同一个数据库,那么对数据库的开销就比较大了,这时可以考虑对内存分页进行优化,例如利用程序缓存处理机制等。 其实真正的内存分页不是那么简单的事情,要实现一个完整的通用的机制,不是一两个小时就能搞定的。首先有一个数据记录的服务器缓存问题,然后才是数据记录分页问题,这个相对好解决一点,但第一个问题就不太好组织。因为缓存问题涉及到数据的缓存位置,缓存时间,删除时间和利于查询的数据组织问题。 数据库分页:

自己实现的百度分页算法

内容显示分页 3个变量 pagSize(每一页显示的记录条数) 自己定义 pageNow(当前页) 由用户指定,初始默认值为1 pageCount总页数,由pageSize和数据库总记录数决定 公式: pageCount=select count(*) from 记录表; if(pageCount%pageSize==0){ pageCount=pageCount/pageSize; }else{ pageCount=pageCount/pageSize+1; } pageNow是传入参数,pageCount是传出参数(getPageCount方法),pageSize内部使用页码分页显示 3个变量 pageNum 每一页显示的页码数和pageSize一样有用你自己定义 pageStart 每一页的页码起始数,由pagNow和pageNum动态计算 pageEnd 每一页的页码结尾数,有pageNow和pageNum动态计算pageStart和pageEnd的计算 /**默认的初始值**/ if(pageNow<=pageNum/2+1{ pageStart=1; pageEnd=pageNum; } if(pageNow>pageNum/2+1){ pageStart=pageNow-pageNum/2; pageEnd=pageNow+pageNum-1; //当然要保证页码的最大数不超过总的页数 if(pageEnd>pageCount){ pageEnd=pageCount; } } 具体程序应用 前台显示 上一页: 上一页 上一页 下一页:

实现分页的js方法