2014-02-19 63 views
0

我有一個項目,用戶發佈JSON到我的API,然後反序列化到一個實體,並堅持到數據庫。 由於運行了一個負載測試工具,它發送了很多請求(使用相同的API密鑰,但作爲不同的'用戶'),我發現我的一些實體正在數據庫中複製。如何防止快速連續在數據庫中創建重複條目? (JPA)

儘管我的代碼檢查數據庫中是否已存在該對象,但其中一些請求正在同時觸發並且繞過檢查。

使用實體管理器,我認爲每個請求都在自己的事務中,但我不知道如何「鎖定」這些事務。除了將創建代碼放入通用java同步塊之外,是否有任何方法可以防止這種重複?

謝謝。

+0

你是如何插入記錄到數據庫中?,em.persist?的@Id設置?,這是你的數據庫? – Koitoer

回答

0

首先,您可以在表上創建唯一約束,如果嘗試插入重複,則會引發異常。

另一件事是將transaction isolation level更改爲更嚴格的(可序列化?)。但是有一個折衷,因爲它會減慢你對數據庫的訪問速度。

我推薦使用第一種方法,尤其是因爲這些衝突不會經常發生,除非在負載測試中。

+0

Glassfish服務器中的事務隔離級別已經可序列化,但數據庫無法更改。 查看以上回答評論:) – Da49

+0

您可以使您的檢查方法同步,您可以編寫自己的插入本機SQL,您可以允許重複的記錄和事後清理,但這些都是解決方法。再次取捨:防止重複或保持性能更重要嗎?但我現在無法想到任何JPA特定的解決方案。 –

0

如果您使用的是關係數據庫(I.E.SQL),那麼最簡單的方法是讓數據庫爲您完成。您和數據庫表的唯一約束:

CREATE UNIQUE INDEX unique_author_name ON authors (first_name, last_name); 

上面的示例具有名爲「authors」的數據庫表。每位作者都有姓氏和名字。約束阻止數據庫存儲2個「馬克吐溫」。

當遇到嘗試添加副本時,JPA將拋出PersistenceException和ConstraintViolationException。

希望幫助:)

+0

我無法在表上創建唯一密鑰,這是問題(由於其他情況,在多租戶數據庫中)。所以我需要一種超越數據庫級別的方式來鎖定其他人,直到創建完成。 – Da49

+0

想到臨時表...不要插入到'真正'表中,而是插入到臨時表中並讓進程複製不重複的行。噢,我的上帝,我不想維護這樣一個系統。 – Gimby