查询数据库后返回Iterator
浏览:41日期:2023-02-13
内容: 既然我们把数据库访问封装起来了,那么如果查询数据库返回的是一系列结果,比如我们从数据库中得到所有人的用户名,然后在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 methodPreparedStatement 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)所以我们必须很小心的释放数据库资源,下面的代码片断展示了这个过程Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try { con = getConnection();//getConnection is your method ps = con.prepareStatement(sql); rs = ps.executeQuery(); ///...........}catch (SQLException ex) { ///错误处理}finally{ try { if(ps!=null) ps.close(); } catch (SQLException ex) { ///错误处理 } try{ if(con!=null) con.close(); } catch (SQLException ex) { ///错误处理 }}很麻烦是不是?但为了写出健壮的程序,这些处理是必须的。大意如下:如果不使用连接池机制, 关闭connection, 必然关闭resultset!如果使用连接池, 所谓的关闭connection, 其实是将连接返回给了连接池,连接对象依然存在, 所以这实际上不叫关闭!2.性能问题如果不是为了模式,用resultset遍历是最快的,比放进Collection在遍历要快很多,装进Collection不也是resultset的遍历吗。在jsp中遍历resultset占用数据库资源的说法是不对的。jsp的后台实现就是servlet。为了模式性能上是要付出代价的。要是你在Collection里面依然采用直接包装ResultSet的方式,在性能上没有丝毫好处。唯一的好处是对jsp程序员屏蔽了RS的访问。Collection需要对java.sql.ResultSet的数据进行page的包装。才有性能上的效果。 Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd 既然我们把数据库访问封装起来了,那么如果查询数据库返回的是一系列结果,比如我们从数据库中得到所有人的用户名,然后在Jsp页面显示出来。这里就有一个普遍疑问,我这个javabean是返回ResultSet到Jsp中还是Collection?我曾经有段时
相关文章: