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