Java JDBC重新读取结果集中的数据

Java JDBC重新读取结果集中的数据,java,sql-server,jdbc,resultset,Java,Sql Server,Jdbc,Resultset,我正在使用MicrosoftJDBC驱动程序(mssqlserver.jar)从SQLServer数据库检索一个简单的结果集。我认为是从[Microsoft JDBC][1]下载的MSSQLS2000驱动程序 我想多次调用getter方法来访问这些值,但执行此操作时会引发以下异常: java.sql.SQLException:[Microsoft][SQLServer2000 JDBC驱动程序]ResultSet无法重新读取列1的行数据 问题是,我正在将数据检索到结果集中。在将结果集传递到代码中

我正在使用MicrosoftJDBC驱动程序(mssqlserver.jar)从SQLServer数据库检索一个简单的结果集。我认为是从[Microsoft JDBC][1]下载的MSSQLS2000驱动程序

我想多次调用getter方法来访问这些值,但执行此操作时会引发以下异常:

java.sql.SQLException
:[Microsoft][SQLServer2000 JDBC驱动程序]
ResultSet
无法重新读取列1的行数据

问题是,我正在将数据检索到结果集中。在将结果集传递到代码中要重用的其他地方之前,我将从结果集访问代码中的数据

代码类似于如下所示:

// build query string
String selectQuery = "SELECT * FROM SomeWhere";

// get the data
Statement statement = sourceConnection.createStatement();
ResultSet rs = statement.executeQuery(selectQuery);

while( rs.next() ) {

    // do my own internal processing 
    doSomethingWithRs(rs);

    // now do something with the record set outside - in subclass
    afterRowCopied(rs);
}

// ...

private void doSomethingWithRs(ResultSet rs) {
    // access data   
    for( int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
        Object o = rs.getObject(i);
        // do something with o...
    }

}
//生成查询字符串
String selectQuery=“从某处选择*”;
//获取数据
语句Statement=sourceConnection.createStatement();
ResultSet rs=statement.executeQuery(selectQuery);
while(rs.next()){
//我自己做内部处理
剂量计(rs);
//现在对记录集outside-in子类执行一些操作
后行复制(rs);
}
// ...
私有void doSomethingWithRs(结果集rs){
//访问数据

对于(int i=1;i我建议只读取一次数据,然后复制到对象数组并将其传递给方法,而不是传递结果集。这可能是更干净的代码。

这似乎是出于设计,根据:

包含BLOB列(例如,文本、ntext或图像数据类型)的ResultSet对象发生此错误。由于大小限制,驱动程序无法按顺序返回BLOB列,因为它不会缓存BLOB数据类型的所有内容

对于ResultSet中的任何行,您可以从左到右读取任何列,并且每列只能读取一次。如果您尝试无序读取列,或者从ResultSet中重新读取列,则可能会收到“症状”部分描述的错误消息

此行为是设计的


您要么需要使用不同的JDBC驱动程序,要么重构代码,以便对任何给定行只读取这些BLOB列一次。无论如何,这是一个好主意,因为重新读取BLOB可能是性能杀手。

冗长的噩梦方法(确实有效),但我只是懒散地实现了大多数getter

编辑

正如我提到的,我使用的是JDK 1.6。但是,在针对JDK 1.7进行编译时,会遇到编译错误:

error: ReadOnlyResultSet is not abstract and does not override abstract method <T>getObject(String,Class<T>) in ResultSet

}

您是否有可能更改驱动程序。您是否可以使用jtds代替SandepNair85,这是一个未来的展望-当然。但现在还不能更改,因为一切都是以数据库为导向的,这将导致大量测试,因为管理层对更换没有100%的信心。您的答案可能是+1'd,但您需要在把这个评论放到Kaffman上之前,t一定是删除了,这正是我要看的-接下来再看一次行()调用了。可能有点过分,但创建一个新类,首先实现ResultSet,然后看看我得到了多少。但是有100多个方法需要重写!prajeesh,我需要结果集的元数据,在那里我操作它超出了超类,所以对象数组在这个实例中是不够的。如果你需要元数据,你可以也可以传递结果集,但不能一次又一次地从中读取。创建一个
列表
,将值读入其中一次,并使用此附加参数调用方法。我不知道它适合多少,但这至少可以使事情以最小的开销进行。
public class ReadOnlyResultSet
    implements ResultSet {
    /**
     * The original data source.
     */
    private ResultSet source;
    /**
     * Cached values for the current row.
     */
    private Object[] values;

    /**
     * Creates a new instance of <code>ReadOnlyResultSet</code>.
     */
    public ReadOnlyResultSet(ResultSet source) {
        this.source = source;
    }

    @Override
    public boolean next() throws SQLException {
        // NOTE:  values[0] will always be null as JDBC is 1 based arrays
        boolean next = source.next();
        if( next ) {
            values = new Object[source.getMetaData().getColumnCount() + 1];
                for(int i = 1; i < source.getMetaData().getColumnCount(); i++ ) {
                    values[i] = source.getObject(i);
                }
            } else {
                // no current row
                values = new Object[] { };
            }

            return next;
        }

        // implement all of the not getter/setter methods
        @Override
        public void close() throws SQLException {
            source.close();
        }

        // implement getters I am interested in
        @Override
        public String getString(int columnIndex) throws SQLException {
            return (String) values[columnIndex];
        }

        @Override
        public String getString(String columnLabel) throws SQLException {
            return (String) values[findColumn(columnLabel)];
        }

        // just too much implementation but hopefully you get the drift