jpa - 在使用 InheritanceType.JOINED 的 JPA 实体层次结构中,与子类的所有关系都会导致父类(super class)表上的外键约束

标签 jpa foreign-keys eclipselink joined-subclass db-schema

我有以下 JPA 2.0 实体

@Entity
@Inheritance(strategy= InheritanceType.JOINED)
public abstract class BookKeepingParent implements Serializable {
    @Id
    protected Long Id;
    ...
}

@Entity
public class Employee extends BookKeepingParent {
    private String name;

    @ManyToOne
    private Role role;
    ...
}

@Entity
public class Role extends BookKeepingParent {
    private String name;
    ...
}

我想让 JPA 为我生成表,因为它可以更轻松地在多个位置安装。我通常会期望它产生这个:
CREATE TABLE bookkeepingparent (
  id bigint NOT NULL,
  dtype character varying(31),
  CONSTRAINT bookkeepingparent_pkey PRIMARY KEY (id )
)

CREATE TABLE role (
  id bigint NOT NULL,
  name character varying(255),
  CONSTRAINT role_pkey PRIMARY KEY (id ),
  CONSTRAINT fk_role_id FOREIGN KEY (id) REFERENCES bookkeepingparent (id)
)

CREATE TABLE employee (
  id bigint NOT NULL,
  name character varying(255),
  role_id bigint,
  CONSTRAINT employee_pkey PRIMARY KEY (id ),
  CONSTRAINT fk_employee_id FOREIGN KEY (id) REFERENCES bookkeepingparent (id),
  CONSTRAINT fk_employee_role_id FOREIGN KEY (role_id) REFERENCES role (id)
)

前两个表在哪里相同,但它生成了 employee这样表:
CREATE TABLE employee (
  id bigint NOT NULL,
  name character varying(255),
  role_id bigint,
  CONSTRAINT employee_pkey PRIMARY KEY (id ),
  CONSTRAINT fk_employee_id FOREIGN KEY (id) REFERENCES bookkeepingparent (id),
  CONSTRAINT fk_employee_role_id FOREIGN KEY (role_id) REFERENCES bookkeepingparent (id)
)

您可以注意到 fk_employee_role_id引用 bookkeepingparent表,而不是 role table 。我有一个很大的 JPA 实体层次结构,我希望 bookkeepingparent 成为其中大多数实体的父类(super class)。这主要是因为一些非常具体的 Id 生成策略和其他簿记事件。这种设计有助于保持本书的所有代码与功能代码分开,让程序员在处理功能代码时不必担心。

所有这些工作正常,直到表的数量增加。现在我们看到,对于所有 ManyToOneOneToOne关系,JPA 正在生成引用父表的外键。对于 200 个奇数表,插入已经很慢,因为所有外键约束都引用了簿记父表,并且每个实体在第一次持久化时都会插入到簿记父表中。我猜这是检查大约 150 个奇怪的约束。

所以,以下是我的问题:JPA 为什么要这样做?这是标准的 JPA 行为吗? (我正在使用 EclipseLink)如果我手动更改数据库架构,他们是否会遇到任何陷阱?

这是我在 StackOverflow 上的第一个问题,我尽力搜索任何现有的答案。如有遗漏,请见谅。谢谢。

最佳答案

您正在使用连接继承,这意味着对于每个类,bookkeepingparenttable 是主表,任何子类表都是次要的。子类的主键是从父类继承的,外键必须引用id,所以设计时都会引用bookkeepingparenttable中的id。不同的提供者允许引用非 pk 字段,但它可能会导致问题,因为解析引用可能需要数据库命中而不是使用缓存。

数据库约束与 JPA 无关,因此您可以根据需要更改它们,只要插入更新和删除仍然符合,就不会影响应用程序。

关于jpa - 在使用 InheritanceType.JOINED 的 JPA 实体层次结构中,与子类的所有关系都会导致父类(super class)表上的外键约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16985779/

相关文章:

java - MySQL 访问被拒绝的 GAE CloudSQL

regex - 如何为相似字符编写 JPQL 查询

java - Hibernate映射异常: Foreign key must have same number of columns as the referenced primary key

sql - 外键中的空值

sql-server - 如何禁用所有表的约束并启用它?

TomEE 上的 Java Eclipselink 给出 "Missing required persistence.xml"

java - 创建 EnityManagerFactory 时出现 NullPointerException

java - 用于选择特定列的 Spring Data JPA 规范

MySQL 使用外键创建表给出 errno : 150

java - 使用 JPA 将一个数据库列映射到两个单独的字段