2011-11-15 43 views
3

我正在更新批量中的大量對象,並且希望忽略任何重複項。 這樣做的最好方法是什麼?Hibernate批處理更新約束違反規則

我的理解是,如果一個ConstrainViolationException被拋出批處理中的所有其他對象將被持久化。

+0

你希望它會是事務性的呢?如果是這樣,您在商店中遇到了一些困難...... – stevevls

回答

2

這是我的解決方案:

private void saveBatch() { 
    StatelessSession session = sessionFactory.openStatelessSession(); 
    Transaction tx = session.beginTransaction(); 

    try { 
     for (Object t : batchList) { 
      session.insert(t); 
     } 
     tx.commit(); 
    } catch (ConstraintViolationException e) { 

     log.info("Duplicate in batch...save individually"); 
     tx.rollback(); 
     session.close(); 
     saveIndividually(); 
     return; 
    } 

    session.close(); 
    batchList.clear(); 
} 

private void saveIndividually() { 
    StatelessSession session = sessionFactory.openStatelessSession(); 
    for (Object t : batchList) { 
     Transaction tx = session.beginTransaction(); 
     session.insert(t); 
     try { 
      tx.commit(); 
     } catch (ConstraintViolationException e) { 
      tx.rollback(); 
      log.warn("Ignoring duplicate: " + t); 
     } 

    } 

    session.close(); 
    batchList.clear(); 
} 
+0

您可能需要在最上面的for-loop中添加session.flush()如下所示:http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html。這將防止內存不足,並且會讓您更快地檢測約束違規。 – benvolioT

+0

不要認爲這會有所幫助。提交自動執行刷新。 –

+0

對,但是如果你的batchList非常大,你可能會用完內存,所以在循環內週期性的刷新可以防止這種情況發生。查看我的第一條評論中的鏈接,獲取更詳細的解釋。 – benvolioT

0

好一個確保一致性的方法是確保所有的實體協會已配置適當的級聯選項(例如,如果你想某一個實體,堅持的時候,也將堅持包含在其協會內的任何新的相關聯的實體,你應該配置cascade =「save-update」)。

如果你不這樣做,理論上的選擇是爲每個批次的操作(如每個實體插入)創建一個單獨的事務,並且如果該事務由於異常而回滾,那麼可以捕獲異常並繼續(可能保留失敗事務的緩存以便稍後重試)。然而,這很可能不實際,因爲與在一個事務中進行所有操作(真正的批量更新)相比,它需要花費很多時間來處理。

就我個人而言,當我遇到這種情況時,我通過JDBC(使用Hibernate架構,並確保具有相同的序列生成)執行批處理操作。這樣更快,你不能更準確地處理這些問題。

+0

不知道級聯與此有什麼關係......我的實體沒有任何關聯。 –

+0

如果entity1對沒有任何級聯選項的entity2具有依賴性,則保存包含entity2的新實例的entity1的新實例將爲您提供ConstraintViolation –