2010-09-08 72 views
7

我正在編寫一個應用程序,將來自第三方數據源的實體同步到我們自己的模式中,其間有轉換/映射步驟。我使用Hibernate來表示並堅持我們自己的模式中的實體。我遇到的一個問題是我的桌子上有一個唯一的多列鍵。我希望看到的行爲類似於upsert:當Hibernate持久存在一個實體並檢測到一個唯一的約束衝突時,它會進行更新。我們正在使用MySQL,它提供了一個INSERT ... ON DUPLICATE KEY UPDATE語法,但我不確定Hibernate如何以及如何使用它。如何使用Hibernate模仿upsert行爲?

我想我總是可以嘗試插入,如果我發現一個異常做了更新,但是這看起來很拙劣和不理想。任何提示乾淨的方式來做到這一點?

回答

4

我們正在使用MySQL,它提供了一個INSERT ... ON DUPLICATE KEY UPDATE語法,但我不確定如何以及是否可以使用Hibernate來使用它?

它看起來像通過重寫這個實體所使用的休眠的sql-insert聲明有人did it。如果你不介意不能移植(也可能使用存儲過程),請看看。

我想我總是可以嘗試插入,如果我發現一個異常做了更新,但是這看起來很拙劣和不理想。任何提示乾淨的方式來做到這一點?

另一種選擇是:

  1. 上唯一鍵
  2. 進行選擇,如果你發現一個記錄,更新
  3. 如果你沒有找到一個記錄,創建

但除非你的過程中鎖定整個桌,你可以面對的一些競爭條件多線程和分佈式環境以及步驟#3可能會失敗。想象一下,兩個併發線程:

主題1:

  • 開始反式
  • 執行上的一個鍵
  • 沒有記錄一個選擇發現
  • 創造紀錄
  • 提交

主題2:

  • 開始反式
  • 執行同一個按鍵上
  • 一個選擇沒有記錄發現
  • 創造紀錄
  • 提交(失敗!因爲線程1是速度更快,具有相同唯一鍵的記錄現在已經存在)

所以,你無論如何都會實現某種重試機制(鎖定整個表(S)是不是一個好的選擇IMO) 。

3

競爭狀態可以用「SELECT ... FOR UPDATE」

+3

如果選擇匹配任何行,沒有行會被「更新」鎖定是可以避免的。競賽條件是不可避免的。 – 2016-12-17 13:53:40