2010-09-07 90 views
2

當我有一個唯一的約束衝突的結果BatchUpdateException有沒有辦法讓我確定批處理插入中的哪條記錄違規?例如,假設我正在通過調用PreparedStatement.executeBatch()執行批量插入,並且捕獲了因爲「ORA-00001:違反唯一約束(ABC.SYS_123)」而導致的BatchUpdateException。當使用Eclipse進行調試時,這個信息的數量大約可以從這個異常中哄出來,但是我想知道哪個實際的插入導致違反唯一約束。有沒有辦法找到這些信息?如何從BatchUpdateException中找到有問題的插入?

我的代碼目前看起來是這樣的(或多或少):

public void batchInsert(final Collection<MyObject> objectCollection) 
{ 
    try 
    { 
     if (connection == null) 
     { 
      connection = getJdbcTemplate().getDataSource().getConnection(); 
     } 

     // get the last entity ID value so we can know where to begin 
     Long entityId = getJdbcTemplate().queryForLong("SELECT MAX(" + MyObject.ID_COLUMN_NAME + 
                 ") FROM " + MyObject.TABLE_NAME); 
     entityId++; 

     // get a date to use for the created and updated dates 
     Date now = new Date(new java.util.Date().getTime()); 

     // set auto commit to false so we can batch save without committing each individual insert 
     connection.setAutoCommit(false); 

     // create the prepared statement 
     String insertSql = "INSERT INTO " + MyObject.TABLE_NAME + " (" + 
          MyObject.ID_COLUMN_NAME + ", VALUE_1, VALUE_2) " + 
          "VALUES (?, ?, ?)"; 
     PreparedStatement preparedStatement = connection.prepareStatement(insertSql); 

     // add a batch entry for each of the SurfaceMetObservations objects 
     for (MyObject object : objectCollection) 
     { 
      preparedStatement.setLong(1, entityId); 
      preparedStatement.setBigDecimal(2, object.getValue1()); 
      preparedStatement.setBigDecimal(3, object.getValue2()); 
      preparedStatement.addBatch(); 
      entityId++; 
     } 

     int updateCounts[] = preparedStatement.executeBatch(); 
     preparedStatement.close(); 
     if (confirmUpdateCounts(updateCounts)) 
     { 
      connection.commit(); 
     } 
     else 
     { 
      connection.rollback(); 
      throw new RuntimeException("One or more inserts failed to execute."); 
     } 
    } 
    catch (SQLException ex) 
    { 
     throw new RuntimeException(ex); 
    } 
} 

我使用Spring的JdbcTemplate和Oracle 11g數據庫,在相關情況。

在此先感謝您的任何建議。

- 詹姆斯

回答

2

BatchUpdateException的Java API文檔:

批量更新 命令後未能正確執行和 的BatchUpdateException被拋出, 驅動程序可能會或可能不要繼續到 批處理 處理剩餘的命令。如果駕駛員在發生故障後繼續 處理,陣列 通過該方法 讓BatchUpdateException.getUpdateCounts 批次中的返回將有一個元件,用於每個命令 而不是隻元件 該誤差之前執行 成功的命令。在驅動程序繼續執行 處理命令的 情況下,對於任何失敗的命令,數組元素 是 Statement.EXECUTE_FAILED。

現在,我不確定您正在使用的Oracle JDBC驅動程序的行爲,但很明顯,提到的任何一種技術都應該可以工作 - 如果在調用返回的數組中有N個元素到BatchUpdateException.getUpdateCounts,那麼批處理中的N個元素已經被處理。或者,如果返回的數組的大小與批處理語句的數量相同,則所有值爲Statement.EXECUTE_FAILED的數組元素在批處理中執行失敗。

+0

感謝Vineet爲我提供了這個非常有用的信息。非常感謝! – 2010-09-08 17:35:29

+0

很高興能有幫助:) – 2010-09-09 04:39:08