PETSTORE分页的疑惑,请板桥指教!

02-10-27 roadbai

看了一下PETSTORE的分页和各位以前的讨论,对PETSTORE的分页程序有个疑问。在PETSTROE中是用返回PAGE类来分页的,每次只返回一页的数据,但是好像每次调用下一页的时候应该执行类似以下的GET方法,这样岂不是每次都去查询一次数据库(rs = ps.executeQuery();),我觉得应该有把第一次查询结果缓存的做法,还是我的理解有问题?请板桥指教!

public Page getProducts(String categoryID, int start,

int count, Locale l)

throws CatalogDAOSysException {

Connection c = null;

PreparedStatement ps = null;

ResultSet rs = null;

Page ret = null;

try {

c = getDataSource().getConnection();

ps = c.prepareStatement("select a.productid, name, descn "

+ "from (product a join "

+ "product_details b on "

+ "a.productid=b.productid) "

+ "where locale = ? "

+ "and a.catid = ? "

+ "order by name",

ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_READ_ONLY);

ps.setString(1, l.toString());

ps.setString(2, categoryID);

rs = ps.executeQuery();

if (start >= 0 && rs.absolute(start+1)) {

boolean hasNext = false;

List items = new ArrayList();

do {

items.add(new Product(rs.getString(1).trim(),

rs.getString(2).trim(),

rs.getString(3).trim()));

} while ((hasNext = rs.next()) && (--count > 0));

ret = new Page(items, start, hasNext);

}

else {

ret = Page.EMPTY_PAGE;

}

rs.close();

ps.close();

c.close();

return ret;

}

catch (SQLException se) {

throw new CatalogDAOSysException("SQLException: "

+ se.getMessage());

}

}

fuck
2002-10-27 21:09

确实如此,这就是分页的两难问题.

缺点:每次只显示一页中的10条也要取所有的即使是100万条记录.

优点:每次取是都是当前数据库的即时记录,如果缓存下来,而数据库又有新的记录你就看不到了.

所以你如果想实时就要全部取出来,如果不想实时可以用ChechRowSet,这样就不要每次从数据库中取了.当然用MYSQL就不用担心了,因为LIMIT可以只取每几到第几条.

其实你也不必过份担心性能问题,因为JDBC的ResultSet实现原理是这样:

不允许序列化:即结果集不能自己被writeObject().它依赖于Connection,

Connection一断,ResultSet就立即清为null.这样ResultSet中并没有保存实际的数据对象,只是保存了二维指针.第一维是记录号,每二位是该记录号的column指针.数据库中数据不管多大,ResultSet本身并不大.只有当你next()到一条记录,然后调用getXXX(col)时才去通过Connection再从数据库中把数据取出来给你.所以即使有一百万条记录,也不过是一万个指点针(JAVA的句柄而已),并没有多大的资源浪费.

cc
2002-10-28 10:13

fuck说得跟banq说得有些出入,如果resultSet真是这样先进的话,那就更用不到把resultset放到Collection里面了,也就更谈不到自己去做Iterator了。

fuck
2002-10-28 11:33

你要注意,ResultSet规定是不能序列化的,也就是它是一个即时的数据结构,依赖于Connection,Connection断了它也就空了,你不能总把Connection占着吧?那只好把ResultSet的值取出来先封装到别的结构中,把Connection断开让给别人啊.

fuck
2002-10-28 11:47

其实你可以看一下ORACLE,MSSQLSERVER,MYSQL等JDBC中ResultSet中是如何实现的.如果ResultSet能保存实际数据,假设先用一条记录(多条记录就开数组或Collection)那么它就应该这样

package org.gjt.mm.mysql;

public class ResultSet implements java.sql.ResultSet

{

HashTable a = new ........

public ResultSet()

{

在构造方法中通过Connection取得数据封装起来

byte[] data1 = Connection.readBytes(column1);

byte[] data2 = Connection.readBytes(column2);

//这只是说明,不一定真的有readBytes()方法,但肯定是先取得数据的原始字节,网络和内存中的任何数据都是无符合序列,JAVA的byte

然后把data1,data2,datan转化为相应的类型.

a.put(column1,data1);

.......................

a.put(columnn,datan);

}

在getXXX()时应该这样

public getString(column1);

{

return a.get(column);

}

}

这样做它是可以保存实际数据的,

但是真实的ResultSet是不允许这样实现的,它的getXXX()

先保存一个全局counter,next()到几,然后

getString(column)

{

byte[] date = Connection.readBytes(counter,column);

}

是在getXXX的时候才去从数据库中取的.

如果不封到别的结构中,Connection就要永远占着,这是不可能的.

2Go 1 2 下一页