2016-02-12 76 views
0

我使用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) 

任何人都可以用除幫助嗎?

+0

一個小建議,讓你的代碼更快,更好。希望這會讓你擺脫這個例外。使用preparedStatement()而不是createStatement()。有關以下鏈接的更多信息。 http://viralpatel.net/blogs/batch-insert-in-java-jdbc/ – justRadojko

+0

@justRadojko,謝謝你的回覆。但是我不能使用'PreparedStatement',因爲它不會以成功查詢更新記錄的方式給出確切的結果,即'affectedRecords'會給我一個滿-2值的數組。 – RAS

回答

1

最佳猜測:通過使用單個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