既然我们把数据库访问封装起来了,那么如果查询数据库返回的是一系列结果,比如我们从数据库中得到所有人的用户名,然后在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)
所以我们必须很小心的释放数据库资源,下面的代码片断展示了这个过程
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的包装。才有性能上的效果。
分享到:
相关推荐
`searchChargeCode()`方法用于查询数据库,返回一个映射,其中每个键代表一天的日期,对应的值是一个包含当天所有工作时间记录的`List`。这样的设计允许高效地访问和显示每一天的详细信息。 在JSP页面中,使用...
在实际项目中,Iterator接口和ListIterator接口的使用非常广泛,例如,在遍历数据库中的记录时,可以使用Iterator接口来遍历记录集;在处理列表时,可以使用ListIterator接口来控制迭代器的行为。 需要注意的是,...
将迭代器功能添加到数据库。 AbstractIterator(db [,options]) db:提供了的当前实例。 选项对象(注意:某些选项取决于Iterator的实现) db :与db参数相同 'next' :确保readStream返回键大于键的原始键...
`Iterator`接口是`Iterable`接口的一个方法`iterator()`返回的,它提供了访问集合元素的机制,包括遍历元素、删除元素等功能。`Iterator`有三个主要的方法:`hasNext()`用于检查是否还有更多元素,`next()`用于获取...
本教程将重点讲解在使用Hibernate时,如何处理查询结果集合,特别是通过`list()`和`iterator()`方法进行数据迭代的操作。 【描述】"http://blog.csdn.net/e421083458/article/details/8794127" 这个链接指向的是一...
1. **用户列表展示**:如上述代码所示,可以用来展示数据库查询结果或从其他数据源获取的用户列表。 2. **商品列表展示**:电商平台中展示商品信息。 3. **日志记录**:在系统后台管理界面中展示日志信息。 #### 六...
3. **迭代器的应用场景**: 迭代器广泛应用于各种场合,如数据读取(例如数据库查询结果),文件系统遍历,以及自定义数据结构(如树或图)的遍历等。 4. **性能考虑**: 迭代器可以避免一次性加载所有数据,因此在...
2) 对大数据量查询时,慎用list()或者iterator()返回查询结果, 3) 对于关联操作,Hibernate虽然可以表达复杂的数据关系 4) 对含有关联的PO(持久化对象)时 5) 在一对多、多对一的关系中,使用延迟加载机制,
它们也可以应用于其他领域,例如数据库查询结果的迭代、文件系统的文件迭代等。 在实际应用中,Iterator接口和ListIterator接口可以用于实现集合的遍历、搜索、删除和添加等操作。例如,在一个社交媒体平台中,...
最后,我们执行查询并返回结果。 在数据库层面,由于我们使用的是MySQL,可以充分利用其支持的LIMIT和OFFSET关键字来实现分页。Hibernate会根据提供的参数动态生成包含这两个关键字的SQL语句。这样,我们就可以从...
这对于数据处理和分析场景尤其有用,比如批量处理数据库查询结果或网络请求响应。 下面是一些使用`async-iterator-all`的关键知识点: 1. **安装**:在项目中引入`async-iterator-all`,通常通过npm进行安装: ``...
这里提到的文档“Java web自定义标签操作数据库.docx”主要展示了如何通过继承`TagSupport`类来创建一个自定义标签,用于在JSP页面上展示从数据库查询到的数据,并实现分页功能。 首先,让我们深入理解自定义标签的...
这个工具类使用了Java的JDBC API来连接数据库并执行SQL查询。`ResultSetMetaData`对象提供了关于结果集列的信息,包括列名和Java类型。注意,在实际项目中,通常会将这些方法封装到一个更复杂的类或框架中,并且会...
标题和描述均聚焦于“Hibernate查询详解”,这一主题在IT领域尤其是Java开发中至关重要,因为Hibernate作为一款流行的Java持久层框架,提供了丰富的查询机制,帮助开发者高效地与数据库交互。以下将深入探讨...
- 记得在完成数据库操作后关闭`Session`和`SessionFactory`,以释放资源。 总结来说,Hibernate通过HQL提供了一种方便的、面向对象的查询方式,使得开发者可以更专注于业务逻辑,而无需过多关注底层的SQL语句。理解...
最后,别忘了在Struts2的配置文件(`struts.xml`)中定义Action和结果,以便Struts2知道如何处理用户的请求和返回结果: ```xml <!-- 其他配置... --> <result name="success">/success.jsp ...
5. 排序后的结果通过并行块迭代器(PX BLOCK ITERATOR)返回给协调器。 并行执行的成本和效率取决于多个因素,包括并行度(Degree of Parallelism, DOP)、CPU利用率、I/O性能和数据量。Oracle会自动计算并行执行的...
例如,查询根类java.lang.Object会返回数据库中所有表的记录: ```java Query query = session.createQuery("from java.lang.Object"); ``` HQL还支持属性查询,即针对实体类的特定属性进行查询。例如,查询User...
使用`sqlite3_open()`函数,传入数据库文件的路径,如果成功,该函数会返回一个数据库句柄。例如: ```cpp sqlite3 *db; int rc = sqlite3_open("my_database.db", &db); if (rc) { std::cerr (db) ; sqlite3_...