【问题标题】:JDBC Re-read Data In ResultSetJDBC 重新读取 ResultSet 中的数据
【发布时间】:2012-02-07 12:35:28
【问题描述】:

我正在使用 Microsoft JDBC 驱动程序 (mssqlserver.jar) 从我的 SQL Server 数据库中检索一个简单的 ResultSet。我认为是从[Microsoft JDBC][1]下载的MSSQL2000驱动程序

我想多次调用 getter 方法来访问这些值,但是当你这样做时会引发以下异常:

java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]ResultSet 无法重新读取第 1 列的行数据。

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

代码类似如下:

// 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...
    }

}

编辑

我为此使用 Java 1.6。

结束编辑

有什么想法吗? 我能想到的就是将带有 ResultSetMetaData 的数据重新打包到一个自定义类中。

没有找到太多关于这个问题的帖子。 Microsoft 网站根本没有任何帮助。

【问题讨论】:

  • 是否可以更换驱动。你能用jtds代替jtds.sourceforge.net
  • sandeepnair85,未来值得期待的东西——绝对是。但是还不能改变,因为一切都几乎是面向数据库的,这将导致大量测试,因为管理层不会 100% 有信心更换。会为您的回答 +1,但您必须先删除,然后再发表此评论

标签: java sql-server jdbc resultset


【解决方案1】:

这似乎是设计使然,根据"ResultSet Can Not Re-Read Row Data"' Error When Reading Data from a JDBC ResultSet Object

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

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

这种行为是设计使然

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

【讨论】:

  • skaffman,这正是我所看到的 - 一旦调用 next() 就读取该行。可能有点矫枉过正,但首先创建一个实现 ResultSet 的新类,看看我能走多远。不过有 100 种方法可以覆盖!
【解决方案2】:

我建议读取一次数据并复制到一个对象数组并将其传递给方法而不是传递结果集。这也可以是更干净的代码。

【讨论】:

  • prajeesh,我需要结果集的元数据,我在超类之外对其进行操作,因此在这种情况下对象数组是不够的。
  • 好吧,如果您需要元数据,您也可以传递结果集,但不要一次又一次地从中读取。创建一个List&lt;Object[]&gt;,将值读入一次,然后使用这个附加参数调用方法。我不知道它会适合多少,但这至少可以以最小的开销让事情顺利进行。
【解决方案3】:

冗长的噩梦方法(确实有效)但我只是懒惰地实现了大多数吸气剂。

编辑

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

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

结束编辑

为此,请创建一个实现 ResultSet 的类(让 Netbeans 添加默认方法实现存根)。然后在构造函数中,存储对初始 ResultSet 的引用。在 next() 中,缓存数组中的值。可能必须对 previous() 和其他设置游标方法执行相同的操作。所以这个类看起来像:

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

}

【讨论】:

    猜你喜欢
    • 2014-06-25
    • 1970-01-01
    • 2017-08-05
    • 2013-03-26
    • 2021-12-31
    • 2014-03-12
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多