java - OneToMany 关系中的复合唯一约束

标签 java spring hibernate spring-mvc jpa

如何让 JPA 在 OneToMany 关系的 Many 端强制执行复合唯一约束的唯一值?

在下面的代码中,我有一个 Person 实体,它有一个内部 id,并且还有一组外部复合 orgids,用于识别患者与其他组织的关系。这些外部复合 ID 由一个用于标识特定组织root组件和一个用于标识由root标识的特定组织内的组件组成。因此,root/extension 的组合在与每个 person 关联的 orgids 集中必须是唯一的。我该如何设置代码来完成此任务?

下面的代码不断尝试在 person_org_id 表 中插入冗余的 root/extension 值,尽管 MySQL 数据库由于下面 DDL 中的 Unique 约束而拒绝这些插入尝试。

@Entity
@Table(name = "person")
public class Person {
    @Id
    @Column(name = "id")
    public Integer id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private Set<PersonID> orgids;

    //other properties, then 
    //getters and setters
}

@Entity
@Table(name = "person_org_id",
uniqueConstraints={@UniqueConstraint(columnNames = {"id_root", "id_extension"})})
public class PersonID {
    @Id
    @Column(name = "id")
    public int id;

    @ManyToOne
    @JoinColumn(name = "person_id")
    private Person person;

    @NotNull
    @ManyToOne
    @JoinColumn(name="id_root")
    private Organization org;

    @NotNull
    @Column(name="id_extension")
    private String orgpersonid;

    //getters and setters
}


CREATE TABLE IF NOT EXISTS person(
  id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY 
  # , other fields
)engine=InnoDB;SHOW WARNINGS;

CREATE TABLE IF NOT EXISTS person_org_id(
  id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  person_id int(11) UNSIGNED NOT NULL,
  id_root varchar(100),
  id_extension varchar(100),
  CONSTRAINT UniqueRootExtKey UNIQUE (id_root, id_extension),
  FOREIGN KEY (person_id) REFERENCES person(id),
  FOREIGN KEY (id_root) REFERENCES organization(root)
)engine=InnoDB;SHOW WARNINGS;

CREATE TABLE IF NOT EXISTS organization(
  root varchar(100) NOT NULL PRIMARY KEY,
  name varchar(200)
)engine=InnoDB;SHOW WARNINGS;

这是在使用 hibernate 和 jpa 的 spring mvc 应用程序中。

最佳答案

本质上,PersonID 表本身并不是一个实体,而是个人和组织之间的链接表。您可以将此关联映射为 Hibernate/JPA 中的映射,使用(在人员方面)组织作为键,使用扩展名作为值。 (您也可以在组织端映射,并以扩展名作为键)

但是,维护 PersonID 表上的 PK 会很困难。然而,这个字段似乎是多余的。您可以删除它并添加通常在 Map 映射表上使用的约束。

就您而言,我将创建一个类结构,其中 person 具有 Map。这将映射为 @ElementCollection,其中包含 PersonID 表的 @CollectionTable 和引用 Organization 表的 @MapKeyJoinColumn。这样,PersonID 就不会生成 ID 列。 PK 将成为对个人和组织的 FK 列的约束。您可以在组织和扩展列中添加对 Fk 的唯一约束,以确保没有重复的 id。

或者,您可以将 PersonID 维护为实体,它存储在映射中,并使用双向关联回 Person,并在 Map 和 PersonID.organization 属性上映射 MapKey。但是,您必须非常确定哪一侧是读写(受控)以及哪一侧是只读(反向)。不必要地更加复杂。

关于java - OneToMany 关系中的复合唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25125022/

相关文章:

java - 我想通过使用另一个带有交换方法的类而不是通常可用的通用交换函数来交换两个数字

spring - WebSocket动态添加和删除Endpoints

hibernate - 如何在 Hibernate 中使用增量来管理多对多关系的版本历史记录?

mysql - 如何在Entity中建立三个表之间的关系?

java - 如何本地化定制的JFileChooser?

java - 如何在eclipse中添加jasypt插件

java - Stream reduce vs Stream.parallel.reduce()

Spring 4 使用 Groovy 设置

java - 在什么情况下我需要提供 spring 类名称作为 bean id 值?

java - JPA Base64 生成器