查询数据库后是返回ResultSet还是返回Collection?

02-08-21 banq
                   

既然我们把数据库访问封装起来了,那么如果查询数据库返回的是一系列结果,比如我们从数据库中得到所有人的用户名,然后在Jsp页面显示出来。

这里就有一个普遍疑问,我这个javabean是返回ResultSet到Jsp中还是Collection?

我曾经有段时间图省事,直接返回ResultSet,然后在我的jsp页面中是大量的ResultSet遍历。这其实还是将数据层和显示层混淆在一起。在EJB CMP中,返回的是Collection,这样偶合性降低,不用在修改数据库结构后,一直修改程序到前台Jsp页面,这和以前的php Asp开发方式没两样。

但是返回Collection效率不是很高,因为意味着在内存中要开辟一个内存存放所有的结果。

我看了http://builder.com.com/article.jhtml?id=u00220020814R4B01.htm这篇文章后,觉得启发很大,返回Iterator就可以了。

Iterator也是个模式,在Jive中大量使用了Iterator,我以前很奇怪,为什么他没事自己写个Iterator,现在知道原因了,这样节省内存,而且效率高。

看下面比较:

public List getUsers() {

ResultSet rs = userDbQuery();

List retval = new ArrayList();

while (rs.next()) {

retval.add(rs.getString(1));

}

return retval;

}

上面是个我们采取返回Collection后最常用的方法,将ResultSet中的用户名加入List再返回,显然这很耗费内存。

使用Iterator返回:

public Iterator getUsers() {

final ResultSet rs = userDbQuery();

return new Iterator() {

private Object next;

public void hasNext() {

if (next == null) {

if (! rs.next()) {

return false;

}

next = rs.getString(1);

}

return true;

}

public Object next() {

if (! hasNext()) {

throw new NoSuchElementException();

}

String retval = next;

next = null;

return retval;

}

public void remove() {

throw new UnsupportedOperationException("no remove allowed");

}

}

}

这里返回的是一个内部类,其实你可以象Jive那样,专门做个Iterator类,这样,这里写得就不那么难看,你自己定义的Iterator和Collection中的Iterator没有任何关系,自己定义了三个方法 hasNext(); next(); remove();这样看上去和Collection的Iterator是一样的。

从自己作的这个Iterator类中看到,这个Javabean只是做了一个指针传递作用,将调用本Javabean的指针传递到ResultSet,这样既提高了效率,节约了内存,又降低了偶合性,这是堪称中间件典型的示范。

既然返回iterator这么好,有人经常用到一个简单的返回Iterator方法:

public Iterator getUsers() {

ResultSet rs = userDbQuery();

List list = new ArrayList()

while (rs.next()) {

list.add(rs.getString(1));

}

return list.iterator();

}

这其实和直接返回list没区别,还是浪费内存。

                   

1
cc
2002-08-21 16:41

太经典了!!终于明白了!!感谢BanQ

wait4friend
2002-08-22 09:37

我经常图省事,直接返回List,今天才明白原来还有这么多道道在里面

chunshui
2002-08-22 13:12

精辟!!!

cathy
2002-08-23 10:44

banq,我看了一下JIVE中的应用. 它先用自己的longList()存放记录集,然后再return new Iterator();这样做不是换汤不换药吗?具体见下:

public Iterator popularForums() {

if (popularForums == null) {

LongList popForums = new LongList(popularForumsNumber);

Calendar cal = Calendar.getInstance();

cal.roll(Calendar.DAY_OF_YEAR, -popularForumsWindow);

Connection con = null;

PreparedStatement pstmt = null;

try {

con = ConnectionManager.getConnection();

pstmt = con.prepareStatement(POPULAR_FORUMS);

pstmt.setString(1, StringUtils.dateToMillis(cal.getTime()));

ResultSet rs = pstmt.executeQuery();

for (int i=0; i < popularForumsNumber; i++) {

if (!rs.next()) {

break;

}

popForums.add(rs.getLong(1));

}

this.popularForums = popForums.toArray();

}

catch( SQLException sqle ) {

sqle.printStackTrace();

}

finally {

try { pstmt.close(); }

catch (Exception e) { e.printStackTrace(); }

try { con.close(); }

catch (Exception e) { e.printStackTrace(); }

}

}

return new DatabaseObjectIterator(JiveGlobals.FORUM, popularForums, this);

}

它为什么这样做呀?我都糊涂了!

24Go 1 2 3 4 ... 24 下一页