既然我們把數據庫訪問封裝起來了,那么假如查詢數據庫返回的是一系列結果,比如我們從數據庫中得到所有人的用戶名,然后在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 boolean 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.關閉數據庫連接rs是否還能使用?
http://dev.csdn.net/develop/article/17/17705.shtm
如下:
在Connection上調用close方法會關閉Statement和ResultSet嗎?
級聯的關閉這聽起來似乎很有道理,而且在很多地方這樣做也是正確的,通常這樣寫
Connection con = getConnection();//getConnection is your method
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
……
///rs.close();
///ps.close();
con.close(); // NO!
這樣做的問題在于Connection是個接口,它的close實現可能是多種多樣的。在普通情況下,你用DriverManager.getConnection()得到一個Connection實例,調用它的close方法會關閉Statement和ResultSet。但是在很多時候,你需要使用數據庫連接池,在連接池中的得到的Connection上調用close方法的時候,Connection可能并沒有被釋放,而是回到了連接池中。它以后可能被其它代碼取出來用。假如沒有釋放Statement和ResultSet,那么在Connection上沒有關閉的Statement和ResultSet可能會越來越多,那么……
相反,我看到過這樣的說法,有人把Connection關閉了,卻繼續使用ResultSet,認為這樣是可以的,引發了激烈的討論,到底是怎么回事就不用我多說了吧。(作者意思是:rs的資源沒有釋放,還用的是連接池中的conn)
新聞熱點
疑難解答