在 JPA 中定义唯一约束

1. 简介

在本教程中,我们将讨论使用 JPA 和 Hibernate 定义唯一约束

首先,我们将探讨唯一约束以及它们与主键约束的区别。

然后,我们将看看JPA的重要注释@Column(unique=true)@UniqueConstraint。我们将实现它们以定义对单个列和多个列的唯一约束。

最后,我们将学习如何在引用的表列上定义唯一约束。

2. 独特的约束

让我们从快速回顾开始。唯一键是表中的一组单列或多列,用于唯一标识数据库表中的记录。

唯一约束和主键约束都为一列或一组列的唯一性提供了保证。

2.1. 它与主键约束有何不同?

唯一约束可确保列或列组合中的数据对于每一行都是唯一的。例如,表的主键充当隐式唯一约束。因此,主键约束自动具有唯一约束。

此外,每个表只能有一个主键约束。但是,每个表可以有多个唯一约束。
简而言之,除了主键映射所需的任何约束之外,还应用唯一约束。

我们定义的唯一约束在表创建期间用于生成适当的数据库约束,也可以在运行时用于对插入更新或删除语句进行排序。

2.2. 什么是单列和多列约束?

唯一约束可以是列约束或表约束。在表级别,我们可以跨多个列定义唯一的约束。

JPA 允许我们使用@Column(unique=true)and@UniqueConstraint在代码中定义唯一的约束。这些批注由架构生成过程解释,自动创建约束。

首先,我们应该强调列级约束适用于单个列,表级约束适用于整个表。

我们将在下一节中更详细地讨论这一点。

3. 设置实体

JPA 中的实体表示存储在数据库中的表。实体的每个实例都表示表中的一行。

让我们首先创建一个域实体并将其映射到数据库表。对于此示例,我们将创建一个Person实体:

@Entity
@Table
public class Person implements Serializable {
    @Id
    @GeneratedValue
    private Long id;  
    private String name;
    private String password;
    private String email;
    private Long personNumber;
    private Boolean isActive;
    private String securityNumber;
    private String departmentCode;
    @JoinColumn(name = "addressId", referencedColumnName = "id")
    private Address address;
   //getters and setters
 }

地址字段是地址实体中的引用字段:

@Entity
@Table
public class Address implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    private String streetAddress;
    //getters and setters
}

在本教程中,我们将使用此Person实体来演示我们的示例。

4. 列约束

准备好模型后,我们可以实现第一个唯一约束。

让我们考虑持有该人信息的Person实体。我们有一个id列的主键。此实体还保存PersonNumber,其中不包含任何重复值。此外,我们无法定义主键,因为我们的表已经有它。

在这种情况下,我们可以使用列唯一约束来确保在PersonNumber字段中没有输入重复值。JPA 允许我们使用具有唯一属性的@Column注释来实现这一点。

在以下部分中,我们将了解@Column注释,然后学习如何实现它。

4.1.@Column(unique=true)

批注类型Column用于指定持久性属性或字段的映射列。

我们来看看定义:

@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Column {
    boolean unique;
   //other elements
 }

唯一属性指定列是否为唯一键。这是UniqueConstraint注释的快捷方式,当唯一键约束仅对应于单个列时非常有用。

我们将在下一节中看到如何定义它。

4.2. 定义列约束

每当唯一约束仅基于一个字段时,我们就可以在该列上使用 @Column(unique=true)。

让我们在personNumber字段上定义一个唯一的约束:

@Column(unique=true)
private Long personNumber;

当我们执行模式创建过程时,我们可以从日志中验证它:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK_d44q5lfa9xx370jv2k7tsgsqt unique (personNumber)

同样,如果我们想限制一个人使用唯一的电子邮件注册,我们可以在电子邮件字段上添加一个唯一的约束:

@Column(unique=true)
private String email;

让我们执行架构创建过程并检查约束:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK_585qcyc8qh7bg1fwgm1pj4fus unique (email)

虽然当我们想在单个列上放置唯一约束时,这很有用,但有时我们可能希望在组合键(列的组合)上添加唯一约束。要定义复合唯一键,我们可以使用表约束。我们将在下一节中讨论这一点。

5. 表约束

复合唯一键是由列组合组成的唯一键。要定义复合唯一键,我们可以在表而不是列上添加约束。JPA 使用@UniqueConstraint注释帮助我们实现这一目标。

5.1.@UniqueConstraint注解

注释类型UniqueConstraint指定唯一约束将包含在为表生成的 DDL(数据定义语言)中。

我们来看看定义:

@Target(value={})
@Retention(value=RUNTIME)
public @interface UniqueConstraint {
    String name() default "";
    String[] columnNames();
}

如我们所见,String String[] 类型的名称和列名称分别是可以为UniqueConstraint注释指定的注释元素。

我们将在下一节中通过示例更好地查看每个参数。

5.2. 定义唯一约束

让我们考虑一下我们的个人实体。人员不应有任何活动状态的重复记录。换句话说,包含personNumberisActive 的键不会有任何重复值。在这里,我们需要添加跨多个列的唯一约束。

JPA 通过@UniqueConstraint注释帮助我们实现这一目标。我们在uniqueConstraints属性下的@Table注中使用它。让我们记住指定列的名称:

@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "personNumber", "isActive" }) })

生成架构后,我们可以对其进行验证:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK5e0bv5arhh7jjhsls27bmqp4a unique (personNumber, isActive)

这里需要注意的一点是,如果我们不指定名称,则它是提供程序生成的值。从 JPA 2.0 开始,我们可以为唯一约束提供一个名称:

@Table(uniqueConstraints = { @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = { "personNumber", "isActive" }) })

我们可以验证相同的内容:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)

在这里,我们在一组列上添加了唯一的约束。我们还可以添加多个唯一约束,这意味着对多组列的唯一约束。我们将在下一节中执行此操作。

5.3. 单个实体的多个唯一约束

一个表可以有多个唯一约束。在上一节中,我们定义了对复合键的唯一约束:personNumberisActive状态。在本节中,我们将添加对安全编号部门代码组合的约束。

让我们收集我们的唯一索引并立即指定它们。我们通过在大括号中重复@UniqueConstraint注释并用逗号分隔来做到这一点:

@Table(uniqueConstraints = {
   @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = {"personNumber", "isActive"}),
   @UniqueConstraint(name = "UniqueSecurityAndDepartment", columnNames = {"securityNumber", "departmentCode"})})

现在让我们看看日志,并检查约束:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)
[main] DEBUG org.hibernate.SQL -
   alter table Person add constraint UniqueSecurityAndDepartment unique (securityNumber, departmentCode)

到目前为止,我们对同一实体中的字段定义了唯一的约束。但是,在某些情况下,我们可能引用了来自其他实体的字段,需要确保这些字段的唯一性。我们将在下一节中讨论这一点。

6. 引用表列的唯一约束

当我们创建两个或多个相互关联的表时,它们通常通过一个表中引用另一个表的主键的列来关联。该列称为“外键”。例如,“人员”和“地址”实体通过addressId字段进行连接。因此,地址 ID充当引用的表列。

我们可以在引用的列上定义唯一的约束我们将首先在单个列上实现它,然后在多个列上实现它。

6.1. 单列约束

在我们的个人实体中,我们有一个引用地址实体的地址字段。一个人应该有一个唯一的地址。

因此,让我们在Person 的地址字段上定义一个唯一的约束:

@Column(unique = true)
private Address address;

现在让我们快速检查一下这个约束:

[main] DEBUG org.hibernate.SQL -
   alter table Person add constraint UK_7xo3hsusabfaw1373oox9uqoe unique (address)

我们还可以在引用的表列上定义多个列约束,我们将在下一节中看到。

6.2. 多列约束

我们可以对列的组合指定唯一的约束。如前所述,我们可以使用表约束来执行此操作。

让我们定义personNumber和地址的唯一约束并将其添加到uniqueConstraint数组中:

@Entity
@Table(uniqueConstraints = 
  { //other constraints
  @UniqueConstraint(name = "UniqueNumberAndAddress", columnNames = { "personNumber", "address" })})

最后,让我们看看独特的约束:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndAddress unique (personNumber, address)

7. 结论

唯一约束可防止两条记录在一列或一组列中具有相同的值。

在本文中,我们学习了如何在 JPA 中定义唯一约束。首先,我们对独特的约束进行了一些回顾。然后我们讨论了@Column(unique=true)@UniqueConstraint注释,分别定义了对单个列和多个列的唯一约束。

与往常一样,本文中的示例可在GitHub 上找到。

你可能感兴趣的:(数据库,java,开发语言)