@UniqueConstraint 和 @Column(unique = true) 在休眠注释中

Posted

技术标签:

【中文标题】@UniqueConstraint 和 @Column(unique = true) 在休眠注释中【英文标题】:@UniqueConstraint and @Column(unique = true) in hibernate annotation 【发布时间】:2013-02-28 15:22:23 【问题描述】:

@UniqueConstraint@Column(unique = true) 有什么区别?

例如:

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = @UniqueConstraint(columnNames = "mask", "group")
)

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

【问题讨论】:

注意:在 Hibernate 5.4 中,当我添加 unique=true 时,方案自动更新程序没有添加索引。 @UniqueConstraint 让它出现了。可能是一个错误。 【参考方案1】:

如前所述,@Column(unique = true)UniqueConstraint 的快捷方式,当它只有一个字段时。

从您给出的示例来看,两者之间存在巨大差异。

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

此代码意味着maskgroup 必须是唯一的,但要分开。这意味着,例如,如果您有一条 ma​​sk.id = 1 的记录并尝试插入另一条 ma​​sk.id = 1 的记录,您将得到一个错误,因为该列应该具有唯一值。这同样适用于团体。

另一方面,

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = @UniqueConstraint(columnNames = "mask", "group")
)

表示 mask + group 组合的值应该是唯一的。这意味着您可以拥有例如 ma​​sk.id = 1group.id = 1 的记录,如果您尝试使用 插入另一条记录mask.id = 1group.id = 2,它会成功插入,而第一种情况则不会。

如果你想让掩码和组分别唯一并且在类级别上是唯一的,你必须编写如下代码:

@Table(
        name = "product_serial_group_mask",
        uniqueConstraints = 
                @UniqueConstraint(columnNames = "mask"),
                @UniqueConstraint(columnNames = "group")
        
)

这与第一个代码块的效果相同。

【讨论】:

创建唯一约束后,我是否可以在我的 JPA 存储库中按名称引用约束来进行查询? @jDub9 不能查询索引。您可以在一个查询中查询掩码和分组列,它会使用该索引来加快处理速度(如果幸运的话),但您不能简单地查询索引。 请注意,尽管 columnNames 必须是数据库中的实际名称。如果使用默认命名策略,则应为mask_idgroup_id【参考方案2】:

来自 Java EE 文档:

public abstract boolean unique

(可选)属性是否为唯一键。这是一个快捷方式 表级别的 UniqueConstraint 注释,对于唯一键时很有用 约束只是一个字段。除任何约束外,此约束均适用 由主键映射和在表级别指定的约束所包含。

见doc

【讨论】:

所以当我使用这个代码时:@Column(unique = true) @ManyToOne(optional = false, fetch = FetchType.EAGER) private ProductSerialMask mask; @Column(unique = true) @ManyToOne(optional = false, fetch = FetchType.EAGER) 私有组组;我有两个索引,但是当使用其他方式时,我有一个索引,它是两列的组合?【参考方案3】:

除了波阿斯的回答......

@UniqueConstraint 允许您命名约束,而@Column(unique = true) 生成一个随机名称(例如UK_3u5h7y36qqa13y3mauc5xxayq)。

有时了解约束与哪个表相关联会很有帮助。例如:

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = 
      @UniqueConstraint(
          columnNames = "mask", "group",
          name="uk_product_serial_group_mask"
      )
   
)

【讨论】:

【参考方案4】:

除了@Boaz 和@vegemite4me 的回答......

通过实现ImplicitNamingStrategy,您可以创建自动命名约束的规则。请注意,您在 Hibernate 初始化期间将命名策略添加到 metadataBuilder

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

它适用于 @UniqueConstraint,但不适用于 @Column(unique = true),它总是生成一个随机名称(例如 UK_3u5h7y36qqa13y3mauc5xxayq)。

有解决此问题的错误报告,所以如果可以,请在那里投票以实现此问题。 这里: https://hibernate.atlassian.net/browse/HHH-11586

谢谢。

【讨论】:

以上是关于@UniqueConstraint 和 @Column(unique = true) 在休眠注释中的主要内容,如果未能解决你的问题,请参考以下文章

Symfony UniqueEntity vs UniqueConstraint vs unique=true

Java中的@UniqueConstraint注解

JPA @UniqueConstraint 看不到列

@UniqueConstraint

为什么@UniqueConstraint不能从超类中找到列?

如何在hbm中做多列UniqueConstraint?