2016-05-08 83 views
0

我有一個表,如(id INTEGER, sometext VARCHAR(255), ....)id作爲主鍵和sometext上的唯一約束。它在Web服務器中使用,請求需要找到與給定sometext對應的id(如果存在),否則會插入新行。防止違反與休眠的唯一約束

這是此表上唯一的操作。此表沒有更新,也沒有其他操作。其唯一目的是持續地遇到值爲sometext的數量。這意味着我不能放棄id並使用sometext作爲PK。

我做到以下幾點:

  • 首先,我諮詢我自己的緩存,以避免任何DB訪問。幾乎總是這樣,我就完成了。
  • 否則,我使用Hibernate Criteria找到sometext所在的行。通常,這個工作,並再次,我完成了。
  • 否則,我需要插入一個新行。

這工作正常,除了有兩個重疊的請求相同sometext。然後結果爲ConstraintViolationException。我需要類似INSERT IGNOREINSERT ... ON DUPLICATE KEY UPDATE(Mysql語法)或MERGE(Firebird語法)。

我不知道有什麼選擇?

AFAIK休眠merge只適用於PK,所以不適用。我猜,原生查詢可能會有所幫助,因爲它可能會或可能不會在第二個INSERT發生時提交。

+0

我不明白你爲什麼不能使用一些文字作爲PK。 – Thilo

+0

另外,爲什麼你不能只是趕上ConstraintViolationException(並忽略它)? – Thilo

+0

@Thilo 1.因爲我需要一個數字而不是文本。這就是我使用'id'的原因。也許我可以使用'sometext'並將數字存儲在另一列(我可以通過其他方式保證唯一性)。 +++ 2.如果我知道它不是由其他東西引起的,我可以。但表名在例外情況下不可用。此外,它發生在'SessionImpl.flush'(而不是INSERT)中,這很可能意味着什麼都不存儲。 – maaartinus

回答

2

讓數據庫處理併發性。純粹爲插入新行開始第二個事務。如果它發生ConstraintViolationException失敗,則只需將該事務回滾並讀取新行。

1

不確定如果重複的可能性很高,那麼如果一些百分比(取決於數據庫)的事務必須失敗插入然後重新選擇,那麼額外的工作會很多。

如果數據庫支持正確的事務,輔助事務會最小化事務添加新文本的時間長度,但線程1事務可能會導致線程2選擇/插入掛起,直到線程1事務被提交或回滾。總體數據庫設計也可能影響事務吞吐量。

我不一定會質疑爲什麼有些文本不能成爲PK,想知道爲什麼你需要打破它。當然,如果某些文本記錄很大,大量文件可能會大大節省空間,這似乎意味着您正在試圖模擬lucene索引來爲您提供完整的文本值列表。

+0

我並不擔心這裏的性能,因爲幾乎所有內容都被緩存覆蓋,重複數據將非常少見。僅供參考編號請求主機地址。它們很短,所以我不需要節省空間,但我也想在數據庫中保留它們的列表。只有當來自* new *客戶端的兩個同時請求(或兩個共享IP的客戶端)發生重複時纔會發生重複,除非進行測試,否則可能不會發生。 – maaartinus