Java 防止JPA违反唯一约束的最佳方法

Java 防止JPA违反唯一约束的最佳方法,java,jpa,constraints,unique,Java,Jpa,Constraints,Unique,我有一个关键字和一个关键字类型作为实体。有很多类型的关键字当尝试持久化类型的第二个关键字时,将违反唯一约束并回滚事务搜索,所以我找到了几个可能性(其中一些来自不同的上下文,所以我不确定它们在这里的有效性)-并建议捕获异常,这对我没有用,因为我最终到达了开始的位置,仍然需要以某种方式保留关键字。 这同样适用于针对不同情况提出的锁定。我想,在和POST中提出的自定义insert语句可能无法正常工作,因为我使用的是Oracle而不是MySQL,并且希望将实现绑定到Hibernate另一种解决方法是尝试

我有一个
关键字
和一个
关键字类型
作为实体。有很多类型的关键字

当尝试持久化类型的第二个关键字时,将违反唯一约束并回滚事务

搜索,所以我找到了几个可能性(其中一些来自不同的上下文,所以我不确定它们在这里的有效性)-并建议捕获异常,这对我没有用,因为我最终到达了开始的位置,仍然需要以某种方式保留关键字。
这同样适用于针对不同情况提出的锁定。我想,在和POST中提出的自定义insert语句可能无法正常工作,因为我使用的是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;
    ...
}


你的上一个解决方案是正确的,IMO。搜索关键字类型,如果找不到,创建它

捕获异常不是一个好的选择,因为

  • 很难知道要捕获哪个异常并使代码在JPA和DB引擎中可移植
  • 在这种异常之后,JPA引擎将处于未确定状态,在这种情况下,您应该始终回滚

但是请注意,使用这种技术,您可能仍然有两个事务并行搜索同一类型,然后尝试并行插入它。其中一个事务将回滚,但其频率将大大降低。

我选择此选项:

一个不同的解决办法将是尝试 首先在代码中检索类型 生成关键字,并将其设置为 关键字(如果找到)或创建新的 一个,如果不是的话


如果您使用的是EJB3.1,并且不介意序列化此操作,那么使用容器管理的并发性的单例bean可以解决此问题

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
公共类关键字类型管理器
{
@锁(LockType.WRITE)
public void upsert(关键字类型关键字类型)
{
//一次只能有一个线程执行此操作。
//您在这里的实现:
// ...
}
@注入
私有关键字类型dao关键字类型dao;
}

从应用程序的视图层,您知道“用户”是在创建新的关键字类型还是在使用现有的关键字类型吗?使用来自文档分析的现有关键字类型。它会改变解决方案吗?
@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "TYPE" }) })
public class KeywordType {

    @Id
    @GeneratedValue
    private long id;

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