2016-09-27 61 views
10

我有一個併發問題,我試圖用一個while循環來解決,它試圖多次保存一個實體,直到它達到一些最大重試次數。我想避免談論是否有其他方法來解決這個問題。我有其他的Stackoverflow的文章。 :)長話短說:對派生的列有一個唯一的約束,幷包含一個數字部分,該部分不斷增加以避免衝突。在一個循環,我:JPA併發問題「在批量發佈時它仍然包含JDBC語句」

  1. 選擇MAX(SOME_VALUE)
  2. 增量結果
  3. 試圖保存新的對象與此新的結果
  4. 明確刷新實體,如果失敗因爲唯一索引,我捕獲了一個DataAccessException。

所有這一切似乎當循環回到步驟1,除了工作,並嘗試選擇,我得到:

17:20:46,111 INFO [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] (http-localhost/127.0.0.1:8080-3) HHH000010: On release of batch it still contained JDBC statements 
17:20:46,111 INFO [my.Class] (http-localhost/127.0.0.1:8080-3) MESSAGE="Failed to save to database. Will retry (retry count now at: 9) Exception: could not execute statement; SQL [n/a]; constraint [SCHEMA_NAME.UNIQUE_CONSTRAINT_NAME]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement" 

和新的異常被捕獲。它看起來像是導致違反唯一約束並引發DataAccessException的第一次刷新不會清除實體管理器的批處理。處理這個問題的適當方法是什麼?我在JPA中使用Spring並且沒有直接訪問實體管理器的權限。我想我可以注射它,如果我需要它但這是一個痛苦的解決這個問題。

回答

5

你不能這麼做 - 一旦你刷新了一些東西,並且失敗並拋出一個異常,事務就會被標記爲回滾。這意味着你沒有處理異常並繼續進行,最終會回滾。 其實它並不重要什麼異常被拋出 - 默認情況下,Spring的事務管理器將在每個未檢查的異常處回滾。它也不會幫助你在這個約束違規的情況下,由於該交易將可能標誌着 - 您可以通過在@Transactional標註明確定義noRollbackFor(提供你正在使用註解驅動的事務)

編輯戰勝它作爲數據庫級別的回滾。