批量更新通过JDBC批处理给人的SQLException通过TransactionImp
问题描述:
我使用EJB3与的Oracle数据库和JDBC。批量更新通过JDBC批处理给人的SQLException通过TransactionImp
我正在开发一个应用程序,我必须解雇25000 UPDATE
查询。
我的代码如下:
public int updateStatus(List<String> idList) {
Connection connection = getConnection(); // Connection initialized properly for oracle db
statement = connection.createStatement();
String sql = null;
for (String id : idlist) { // idList is properly filled
sql = "UPDATE TBLTEST SET STATUS = 'FIXED' WHERE ID = '" + id + "'";
statement.addBatch(sql);
}
int[] affectedRecords = statement.executeBatch();
}
请注意,在这种方法写的类,被注释为
@TransactionManagement(TransactionManagementType.CONTAINER)
此代码工作高达8000个查询完美的罚款。欲了解更多id
S,它抛出以下异常:
org.jboss.util.NestedSQLException: Transaction TransactionImple < ac, BasicAction: 0:ffffc0a80272:1652:56bd6be5:57e status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK; - nested throwable: (javax.transaction.RollbackException: Transaction TransactionImple < ac, BasicAction: 0:ffffc0a80272:1652:56bd6be5:57e status: ActionStatus.ABORTED > cannot proceed STATUS_ROLLEDBACK)
at org.jboss.resource.adapter.jdbc.WrapperDataSource.checkTransactionActive(WrapperDataSource.java:165)
at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransactionActive(WrappedConnection.java:843)
at org.jboss.resource.adapter.jdbc.WrappedConnection.checkStatus(WrappedConnection.java:858)
at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:835)
at org.jboss.resource.adapter.jdbc.WrappedConnection.createStatement(WrappedConnection.java:183)
任何人都可以用除帮助吗?
答
最佳猜测:通过使用单个SQL语句而不是PreparedStatement
,您强制驱动程序将所有语句(> 400k字符数据)发送到数据库和数据库,以解析所有400k字符,这将在一些时间和破坏的东西(例外情况不明确,因为它隐藏了造成异常的地方或破坏)。
如何解决:
围棋的“不太多”声明同时个别批次 - 说... 1000:
public int updateStatus(List<String> idList) {
List<Integer> affectedRecords = new ArrayList<Integer>(idList.size());
try(Connection connection = getConnection();
Statement statement = connection.createStatement()) {
int count = 0;
for (String id : idList) {
statement.addBatch("UPDATE TBLTEST SET STATUS = 'FIXED' WHERE ID = '" + id + "'");
//Execute after 1000 rows
if(++count % 1000 == 0) {
int[] result = statement.executeBatch();
//Utility Method - you need to implement to add int[] into the List
addResults(affectedRecords, result);
statement.clearBatch();
}
}
//In need of final execute?
if(count % 1000 > 0) {
// For good measure execute once more
int[] result = statement.executeBatch();
//Utility Method - you need to implement to add int[] into the List
addResults(affectedRecords, result);
}
} catch(SQLException se) {
se.printStackTrace();
}
}
+0
谢谢Jan,这在一定程度上有所帮助。但达到某一点后,这也失败了。 – RAS
一个小建议,让你的代码更快,更好。希望这会让你摆脱这个例外。使用preparedStatement()而不是createStatement()。有关以下链接的更多信息。 http://viralpatel.net/blogs/batch-insert-in-java-jdbc/ – justRadojko
@justRadojko,谢谢你的回复。但是我不能使用'PreparedStatement',因为它不会以成功查询更新记录的方式给出确切的结果,即'affectedRecords'会给我一个满-2值的数组。 – RAS