簡體   English   中英

防止JPA違反唯一約束的最佳方法

[英]Best way to prevent unique constraint violations with JPA

我有一個KeywordKeywordType作為實體。 有很多類型很少的關鍵字。

當嘗試保留類型的第二個關鍵字時,違反了唯一約束,並且回滾了事務。

搜索SO我發現了幾個可能性(其中一些來自不同的上下文,因此我不確定它們在這里的有效性)- 這篇文章這篇文章建議捕獲Exception,這對我毫無用處,因為我最終從我開始的地方開始並且仍然需要以某種方式保留關鍵字。
同樣適用於此處針對不同情景建議的鎖定
我猜這篇文章中提出的自定義插入語句將無法正常工作,因為我使用的是Oracle而不是MySQL,並且希望將實現與Hibernate綁定在一起。

另一種解決方法是嘗試首先在生成關鍵字的代碼中檢索類型,然后在找到的關鍵字上進行設置,否則將其創建。

那么,什么是最好的-最健壯,可移植(針對不同的數據庫和持久性提供程序)和理智的方法呢?

謝謝。

涉及的實體:

public class Keyword {

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "VALUE")
    private String value;

    @ManyToOne
    @JoinColumn(name = "TYPE_ID")
    private KeywordType type;
    ...
}

@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "TYPE" }) })
public class KeywordType {

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "TYPE")
    private String type;
    ...
}

IMO是您的最后一個解決方案。 搜索關鍵字類型,如果找不到,請創建它。

捕獲異常不是一個好的選擇,因為

  • 很難知道要捕獲哪個異常並使您的代碼可跨JPA和DB引擎移植
  • 發生此類異常后,JPA引擎將處於不確定狀態,在這種情況下,您應始終回滾。

但是請注意,使用這種技術,您可能仍然有兩個事務並行搜索同一類型,然后嘗試並行插入。 事務之一將回滾,但它的頻率要低得多。

如果您使用的是EJB 3.1,並且不介意將此操作序列化,那么使用容器管理的並發性的單例bean可以解決此問題。

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class KeywordTypeManager
{
    @Lock(LockType.WRITE)
    public void upsert(KeywordType keywordType)
    {
        // Only one thread can execute this at a time.
        // Your implementation here:
        // ...
    }

    @Inject
    private KeywordTypeDao keywordTypeDao;
}

我會選擇這個選項:

另一種解決方法是嘗試首先在生成關鍵字的代碼中檢索類型,然后在找到的關鍵字上進行設置,否則將其創建。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM