如何使用 Hibernate 获取两个字段的唯一键?

Posted

技术标签:

【中文标题】如何使用 Hibernate 获取两个字段的唯一键?【英文标题】:How to get a unique key for two fields with Hibernate? 【发布时间】:2010-10-31 02:20:19 【问题描述】:

我有一个实体类的两个字段,我不希望它们是唯一的,而是用作键的复合字段,该键本身必须是唯一的。例如,我有两个字段(名称和版本),其他记录可以相同,但它们必须是唯一的。使用 Hibernate(带注释)的最佳方法是什么?我正在将 Hibernate Validator 用于其他字段,但我不确定使用它来验证两个字段是否共同构成一个唯一键。我正在使用一个通用实体类,它有一个 id 通用类型,可以换成复合键类,但我还没有让它很好地工作。

【问题讨论】:

你想在两列上设置一个“唯一约束”,还是在包含两列的表上设置一个“主键”? 我想要一个对两列的唯一约束。例如名称和版本的组合必须是唯一的。所以我可以在记录#1 (name=abc/version=1) 和记录#2 (name=abc/version=2) 的表中有两条记录,但在记录#1 (name=abc/version=2) 的表中没有两条记录=abc/version=1) 和记录#2 (name=abc/version=1)。 【参考方案1】:

这将在数据库上创建一个唯一键:

@Table( name = "MYTABLE",
        uniqueConstraints =  @UniqueConstraint( columnNames =  "NAME", "VERSION"  )  )

这将由数据库在更新或持久化时强制执行。

如果您想使用 Hibernate Validator 强制执行此操作,您需要编写自己的自定义验证器。

【讨论】:

如果 pk 是名称和版本,应该在实体中写入什么作为 pk ?... @yoav.str - 如果 PK 是名称和版本,您应该使用带有 @Id/@IdClass 或 @EmbeddedId/@Embeddable 的复合主键 @mtpettyp - 如果我想在违反该唯一约束的情况下显示一条消息?我可以在我的 SPRING MVC 应用程序中使用文件 message.properties 来按照模式 ValidationAnnotationClass.modelObject.fieldName 执行它吗?【参考方案2】:

我们通常会将这两个字段包装在一个标记为@Embeddable 的内部键类中。例如:

@Entity
public class Foo 

  @EmbeddedId()
  private Key key;
  ...

  @Embeddable
  public static class Key 
    @Column(nullable=false)
    private String name;
    @Column(nullable=false)
    private int version;

    protected Key () 
      // for hibernate
    
    public Key (String name, int version) 
      this.name = name;
      this.version = version;
    
    ...
    // You probably want .equals and .hashcode methods
  

【讨论】:

以上是关于如何使用 Hibernate 获取两个字段的唯一键?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JPA 和 Hibernate 连接两个不相关的实体

Hibernate 生成策略和缓存策略

hibernate系列之四

如何使用hibernate避免遇到违反唯一约束的问题?

hibernate之主键生成策略

Hibernate多表关系配置——一对一关系映射