JiveJdon Community Forums
在线99人   首页   主题表   培训咨询   标签   查搜   注册    登陆 RSS
首页 » 论坛 » 语言平台技术讨论
???en_US.forumThreadPrev.name??? 上一主题
RSS google yahoo 365Key网摘 CSDN网摘 添加到百度搜藏 POCO网摘 新浪ViVi QQ网摘
???en_US.forumThreadNext.name??? 下一主题
1 2 3 4 ... 8 Go 共有 118 回复(8页) 阅读830次
 发表新帖子   回复该主题贴
banq



发表文章: 11282
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 70人关注
查询数据库后是返回ResultSet还是返回Collection? 2002年08月21日 14:23 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
标签                    
既然我们把数据库访问封装起来了,那么如果查询数据库返回的是一系列结果,比如我们从数据库中得到所有人的用户名,然后在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没区别,还是浪费内存。

cc



发表文章: 275
注册时间: 2002年08月07日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月21日 16:41 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
太经典了!!终于明白了!!感谢BanQ
wait4friend



发表文章:
注册时间: 2002年08月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月22日 09:37 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
我经常图省事,直接返回List,今天才明白原来还有这么多道道在里面
chunshui



发表文章:
注册时间: 2002年08月05日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月22日 13:12 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
精辟!!!
cathy



发表文章:
注册时间: 2002年08月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 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);
}

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



发表文章:
注册时间: 2002年08月07日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月23日 10:48 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
那么,有没有考虑到数据库连接要一直维持的开销呢?
scorpio_leon



发表文章: 17
注册时间: 2002年08月07日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月23日 10:52 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
刚发完帖就看到楼上的jive代码,对呀,必须一次将数据全部取出组成大对象,然后再返回次对象的连接,使用Iterator我想很大部分是因为它的速度快,因为我们不需要随机访问对象
banq



发表文章: 11282
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 70人关注
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月23日 14:20 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
longList()是缓冲,从缓冲里装入Iterator和从数据库resultset中装入是一样的。
wait4friend



发表文章: 37
注册时间: 2002年08月22日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月23日 16:24 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
使用缓冲,速度到快了,但是也耗内存亚?这和List.iterator()由什么区别呢?
banq



发表文章: 11282
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 70人关注
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月23日 16:37 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
不一样,
首先缓冲大小可以根据内存人为控制的,
缓冲是对那些经常访问的帖子进行的,不是所有的帖子。
浆糊



发表文章:
注册时间: 2002年08月06日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月24日 12:28 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
板桥,你的代码好像有些问题。在iterator中直接实现rs的遍历,最后没有释放数据库连接。在 hasNext方法中应该在rs.next()为false的时候关闭数据库连接。
还有,这样的实现方式对数据库连接的占有时间太长,我感觉。而且如果重复访问这个iterator都会重复调用数据库,如果直接返回一个iterator对象,在重复访问的时候效率会高一些。
banq



发表文章: 11282
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 70人关注
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月24日 22:11 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
数据库操作已经在ResultSet rs = userDbQuery();
的userDbQuery()中都完成,返回的是一个Resulset
xxff



发表文章:
注册时间: 2002年08月25日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Iterator在我的程序中该如何使用呢? 2002年08月25日 10:00 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
我编写的一个类DBUtility,原来我使用map实现,根据你的方法,采用Iterator好,但如何在jsp页面中使用呢?

public static Map getSQLResults(String aSQL) { // 功能描述:执行SQL语句-查询操作,对数据库操作
/** 输入参数:aSQL-一个SQL执行语句,能执行的语句
* 输出参数:Map-以Map类型返回的表格形式数据。
* 关键字:字段名称
* value :查询值,以有序的Vector保存【目前,只以String形式保存,不以Number等其它形式保存;另外返回接口为List】
* 异常:没有正确运算时,得到Map的消息对【__ExceptionMessage-Message(String)】
* 没有查询到数据时,返回Map的消息对【__ExceptionMessage-Message(String)】
* 附加说明:getSQLResults()规定了数据库表查询的操作行为
* map规定了数据库表查询得到的数据表达方式
* ?考虑大数据量的部分记录操作【可以设置指针操作:从哪开始,到哪结束,多少条记录】
*/
TreeMap map = new TreeMap();
HiPool pool = null; Connection conn = null;
try {
// 1 打开数据库 2 获得到值 3 获取到结构 4 赋值给map的关键字 5 由关键字得到值赋予Vector 6 保存Vector到map中
pool = HiPool.getInstance();
conn = pool.getConnection();
Statement stmt = conn.createStatement();
// 2 获得到查询值 2002/08/25
ResultSet rs = stmt.executeQuery(aSQL);
// 3 获取到查询结构 2002/08/25
ResultSetMetaData rsmd = rs.getMetaData();
Vector[] rows = new Vector[rsmd.getColumnCount()];
while(rs.next()) {
for(int i=0; i<rsmd.getColumnCount(); i++) {
if (rows == null) rows = new Vector();
rows.add(rs.getString(i+1));
// 4 保存字段名、字段值到变量中
map.put(rsmd.getColumnName(i+1), rows);
}
/**
* 字段名1 Vector[记录数]
* 字段名2 Vector[记录数]
* 字段名3 Vector[记录数]
*/
}
rs.close(); stmt.close();
pool.free(conn);
conn = null;
if (map.isEmpty()) map.put("__ExceptionMessage", "使用DBUtility工具,没有查询到符合查询条件的数据");
else map.put("__ExceptionMessage","使用DBUtility工具,已经查找出符合查询条件的记录");
} catch (Exception e) {
map.clear();
map.put("__ExceptionMessage",e);
if(conn != null) {
pool.free(conn);
try { conn.close(); } catch (SQLException e_1) { map.put("__ExceptionMessage", e_1);}
conn = null;
}
}
return map;
}
banq



发表文章: 11282
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 70人关注
Re: Iterator在我的程序中该如何使用呢? 2002年08月25日 11:54 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
首先你将从pool = HiPool.getInstance();开始的代码封装在userDbQuery()这个Javabean中,然后你再编写个Javabean 返回Iterator,这样在你的Jsp中遍历这个iterator就可以输出显示
这样 你的Jsp中Java代码要干净多了
浆糊



发表文章: 244
注册时间: 2002年08月06日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: 查询数据库后是返回ResultSet还是返回Collection? 2002年08月26日 09:15 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
那你在什么地方关闭数据库连接?如果 你在数据库连接关闭之后还能用rs来访问db?
标签                    
共有 118 回复(8页) Go 1 2 3 4 ... 8
???en_US.forumThreadPrev.name??? 上一主题
  Go back to the topic 返回本主题   Go back to the topic listing返回主题列表    返回页首返回页首
???en_US.forumThreadNext.name??? 下一主题
正在读取,请等待...
查询本论坛内 回复超过的热门帖子
标题
 
粗体: [b]文本[/b] 斜体: [i]文本[/i] 下划线 [u]文本[/u] 插入网上的图片 [img]http://wwww.xxxx.com/img.ext[/img] 插入代码 [code]程序代码[/code]  插入url链接 [url]http://url[/url] / [url=http://url]URL加下滑线[/url] 上传图片 word文档 Txt等附件
内容
  提交时自动拷贝以上内容到剪贴板 Ctrl+V可取出;提问题前先查询标签列表

使用帮助 手机m.jdon.com RSS add to google add to yahoo
解惑之道在J道 ,打造中国最具影响力的的软件架构社区 推荐FireFox或Chrome快速浏览本站
OpenSource JIVEJDON Powered by JdonFramework Code © 2002-10 jdon.com

anti spam