数据库批量查询分页的完美解决之道

数据库批量查询分页的完美解决之道
(Pet Store中DAO模式和与Jive中Iterator模式的合并)

在阅读本文之前,你需要了解Pet Store的J2EE模式(见我"设计模式在EJB中应用"以及http://java.sun.com/blueprints/patterns/catalog.html)

在Pet Store中的CatalogDao使用了DAO模式,从而完成Fast-Lane Reader模式,以便能快速的输出数据库元素列表,同时使用for page-by-page iteration完成每页的输出显示。

在CatalogDAOImpl 中基本返回的是Page,也就是说,在CatalogDAOImpl的具体JDBC数据库查询时,就将Page功能融入其中,从而一步到位的完成输出显示。

但在实际系统应用中,我们都有用户权限约束,也就是说,并不是每条数据库记录都能被显示输出,有些用户就只能看到他被授权看到的的记录。

Jive中的Iterator模式就很好的解决了这个问题,Jive中使用Proxy模式完成用户权限级别的验证,同时为了更快的获得数据库记录和节约内存,Jive专门建立了自己的Iterator模式,这些一开始让人疑惑,直接使用Collection的Iterator不是更好,虽然简单方便了,但是前提是在内存中要先开辟一块Collection内存,如果数据库记录很大,将耗费很多内存,致使系统瘫痪(细节讨论见
http://www.jdon.com:81/jive/thread.jsp?forum=16&thread=302)

Jive的Iterator不只是传递了数据库指针,而且加载了权限验证功能,因此,这一模式是实用可行的,那么在我们自己的EJB应用中如何综合这两个系统的模式优点?

这其中应该有很多中间方案可行,如果你有兴趣可以贴出你的想法,我目前采取的是DAO模式和Jive的Iterator模式集合,也就是说,在自己的EJB中不直接返回Page 而是返回Iterator,这个Iterator是类似Jive中的DatabaseObjectIterator。

简单的说,由于Jive不是EJB架构,所以,将Jive中的访问数据库段用DAO模式替代,其他都可以照搬Jive的Iterator模式,关于前端JSP页面的分页输出,这时可以参考Pet Store的page-by-page iteration模式,也就是说,根据Iterator模式再拓展写Page,结构和功能类似Pet store的Page.

这里只提供一个大体思路,如果要写透彻真是很长,看看平常我们以前用ASP PHP做的数据库查询分页的简单功能蕴含这么多新的思想,
其实这些思想也是在ASP PHP应付大数据库量失败的总结,所以软件质量控制是显得多么重要。

不满意啊 , 我不会ejb :<

这个其实也没有用EJB DAO模式其实就是平时的JDBC的直接访问,不需要EJB环境也可运行。

道友Michael Zeng在整理相关资源情况下开发一个非J2EE的基本的应用包Utilities.zip,可以通过CVS参与这个应用包的开发。

对,我现在就是仿照pet Store例子来做的。
在EJB中使用page-by-page iteration模式真是很好。
虽然我现在没有用到ejb,但以上方法照样实用。

实际上Pet Store中提供了几种访问数据的接口,对于大量数据查
询用DAO(直接使用JDBC),对于一些业务逻辑的操作使用EJB。我
觉这样很好。

大致看了一些,写的很好啊!!!真的狠感谢啊!!!

hi,this is Michael, all of you can call me Mike or wait4friend.谢谢楼上兄弟的鼓励,我其实也想参与CVS的开发,但是在公司里upload之类的操作是被严格限制的。残念!

我如坠云雾

wait4friend !

看了你的程序,有些地方不解。

为什么返回的都是String [] 数组呢?为什么不返回一个Object呢???如:

public String[] get(int index) throws Exception;

如果需要返回Object的话,比如一个Item对象,可以在RowMapper.rowMap()里面提供ResultSet.getXXX()到item.setXXX()的转换。而且DataList的资料中也是这样介绍的。这样的话,针对每一个不同的对象,都要提供一个RowMapper的子类。我写这个类的时候,主要目的是通过select来得到指定列的值进行显示,有是不需要全部的值。如:
tableXXX有三列(id, name, age),我只需要前两个,于是
select id, name form tableXXX
使用 String[] value = get(int)返回的String[]中就只有两个元素, values[0] = idvalue, values[1] = namevalue,使用数组是为了是用for在页面上进行显示。使用getColumns()得到的数组只有id和name两个值,可以作为html中table的表头th
如果各位有好的解决方案,请在这里贴出来,大家参考。

> 对,我现在就是仿照pet Store例子来做的。
> 在EJB中使用page-by-page iteration模式真是很好。
> 虽然我现在没有用到ejb,但以上方法照样实用。
>

andrawu,你能详细的告诉我什么是page-by-page iteration模式嘛?
我现在很想知道使用它进行分页的具体实现?我们现在用的系统架构就是pet store!
老大,帮帮忙!:) 小弟不胜感激!!!

“如果需要返回Object的话,比如一个Item对象,可以在RowMapper.rowMap()里面提供ResultSet.getXXX()到item.setXXX()的转换。”

这句话不是我要的结果啊,我是要String[] => Object ,这个可不可能实现?

你说你想取得select后的少数字段,这一点我可以理解。但我想的是,页面访问的应该是Iterate中的javaBeans,而不是直接从数据库取出的string[]或resultSet或Iterate中的string[]。
还有就是如果取出string[],你怎么确定其中数据的类型?

1."我是要String[] => Object "我不明白你的意思
2."页面访问的应该是Iterate中的javaBeans",调用大致如下:JSP----Iterator.next()----DataListChunk.get(i)----DataList.get(i)----RowMapping.rowMap(rs)----ResultSet.getString(i),经过几个delegate,最后使用ResultSet。其中下划线部分对于JSP程序员是透明的。
3。“怎么确定其中数据的类型”,这里我取了一点巧。因为我的目的是在Web上进行显示,都要使用out.println(xxx)。而JDBC中的大部分数据类型都可以使用ResultSet.getString()取出来,所以...

你这个流程是JSP程序员调用的,如果是在Bean中取出resultSet封装逻辑,那么该如何调用呢??

参见AbstractPage