这里是我按照banq的源代码更改之后的版本
不知道这样的实现是否好一点?
请各位指教
这些方法是一个AbstractClass中的方法,具体的业务对象实现必须实现resultToObject方法


protected abstract Object resultToObject(ResultSet result) throws Exception;

protected Iterator resultToIterator(ResultSet result) {
return new ResultSetIterator(result);
}



protected class ResultSetIterator implements Iterator {

private ResultSet resultSet;
private Object next;

public ResultSetIterator(ResultSet result) {
this.resultSet = result;
}

public boolean hasNext() {
try {
if (next == null) {
if (!resultSet.next()) {
return false;
}
next = resultToObject(resultSet);
}
return true;
} catch (Exception e) {
return false;
}
}

public Object next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Object returnValue = next;
next = null;
return returnValue;
}

public void remove() {
throw new UnsupportedOperationException("No remove allowed");
}

}

非常好,说明你已经有复用的意识习惯了。
总结成抽象方法后,类似一个小框架了,可以根据具体情况复用。

照我个人的理解
用Iterator这种方式
相当于包装了一下ResultSet
那么
是否我无法利用这个Iterator接口来直接获取纪录的总数?
只能遍历一遍么?那效率太低了啊 ]

这个问题呢?
烦请banq或其他DX解答一下
谢谢

要获得记录总数,当然不能遍历一遍,这个取决于你上下文,如果你上文已经遍历,那么取总数也是顺便的事情;或者你可以从resulset获得总数也可以直接操作数据库获得总数。

方法是哪个?
很抱歉
我很少接触JDBC阿……

JDBC不支持直接获得记录数
高版本的jdbc支持吧,听说只能用select count来得到记录数
2 banq:
我以前做过取出resultset后关闭连接,这个resultset也不能用了

看看Jive里面是怎么做的,他专门做了一个Iterator类,专门用来遍历数据。

现在关键是ResultSet如何导入,在jive中是使用了一个objectFactory内部类来导入ResultSet 和楼上代码有相同思路,但是做得更巧妙,在DatabaseObjectIterator构造函数中,转换ResultSet结果为Object.

构造函数中这种方法也有些疑惑,好像不是很节省内存.



public class DatabaseObjectIterator implements Iterator {

private long [] elements;
private int currentIndex = -1;
private Object nextElement = null;

private DatabaseObjectFactory objectFactory;

public DatabaseObjectIterator(int type, long [] elements,
final Object extraObject)
{
this.elements = elements;

// Load the appropriate proxy factory depending on the type of object
// that we're iterating through.
switch (type) {
// FORUM
case JiveGlobals.FORUM:
// Create an objectFactory to load forums.
this.objectFactory = new DatabaseObjectFactory() {
ForumFactory factory = (ForumFactory)extraObject;

public Object loadObject(long id) {
try {
Forum forum = factory.getForum(id);
return forum;
}
catch (ForumNotFoundException mnfe) { }
catch (UnauthorizedException ue) { }
return null;
}
};
break;
// Otherwise, an invalid value was passed in so throw an exception.
default:
throw new IllegalArgumentException(
"Illegal type specified");
}
}

/**
* Returns true if there are more elements in the iteration.
*
* @return true if the iterator has more elements.
*/

public boolean hasNext() {
// If we are at the end of the list, there can't be any more elements
// to iterate through.
if (currentIndex+1 >= elements.length && nextElement == null) {
return false;
}
// Otherwise, see if nextElement is null. If so, try to load the next
// element to make sure it exists.
if (nextElement == null) {
nextElement = getNextElement();
if (nextElement == null) {
return false;
}
}
return true;
}

/**
* Returns the next element.
*
* @return the next element.
* @throws NoSuchElementException if there are no more elements.
*/

public Object next() throws java.util.NoSuchElementException {
Object element = null;
if (nextElement != null) {
element = nextElement;
nextElement = null;
}
else {
element = getNextElement();
if (element == null) {
throw new java.util.NoSuchElementException();
}
}
return element;
}

/**
* Not supported for security reasons.
*/

public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}

/**
* Returns the next available element, or null if there are no more
* elements to return.
*
* @return the next available element.
*/

public Object getNextElement() {
while (currentIndex+1 < elements.length) {
currentIndex++;
Object element = objectFactory.loadObject(elements[currentIndex]);
if (element != null) {
return element;
}
}
return null;
}
}

/**
* An interface for loading Jive database objects.
*/

interface DatabaseObjectFactory {

/**
* Returns the object associated with <code>id</code> or null if the
* object could not be loaded.
*
* @param id the id of the object to load.
* @return the object specified by <code>id</code> or null if it could not
* be loaded.
*/

public Object loadObject(long id);
}

在上面代码中的构造函数中,功能类似ResultSet,但不是ResultSet,ResultSet是将结果全部一下子查询出来,但上面代码中
Forum forum = factory.getForum(id);
以ID查询单条记录,那么DatabaseObjectIterator 传递的指针实际是factory.getForum(id)。

我是前天晚上看过这个Iterator类,觉得它做得极其精巧,看着这样的程序真是一种享受.

研究了这么长时间的resultSet转换!

越看越糊涂!

DatabaseObjectIterator的封装性真差!

到底有没有完美解决?

为什么这么说,对于JIVE的forum,thread,message等的resultset返回解决方案用这种方式是非常精巧的.

注意:完美解决之道中没有resultSet概念

我靠 ! ! 先不看banq写的文章 ,呆会再看 !

刚刚又研究了一下,终于稍微看懂了一些!

人家jive根本不是一个select语句出一个DatabaseObjectIterator,它是有选择的用DatabaseObjectIterator,像这种最基本的select语句:SELECT threadID from jiveThread WHERE forumID=? 它根本就直接放到自己定义的List


try {
con = ConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_FORUMS);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
forumList.add(rs.getLong(1));
}
}

只有一些放到cache中的,才使用人世间最难看懂的方法,比如: private static final String POPULAR_THREADS =
"SELECT threadID, count(1) AS msgCount FROM jiveMessage " +
"WHERE modifiedDate > ? GROUP BY threadID ORDER BY msgCount DESC";

就是不服!