Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在使用InheritanceType.join的JPA实体层次结构中,与子类的所有关系都会导致超类表上的外键约束_Jpa_Foreign Keys_Eclipselink_Joined Subclass_Db Schema - Fatal编程技术网

在使用InheritanceType.join的JPA实体层次结构中,与子类的所有关系都会导致超类表上的外键约束

在使用InheritanceType.join的JPA实体层次结构中,与子类的所有关系都会导致超类表上的外键约束,jpa,foreign-keys,eclipselink,joined-subclass,db-schema,Jpa,Foreign Keys,Eclipselink,Joined Subclass,Db Schema,我有以下JPA2.0实体 @Entity @Inheritance(strategy= InheritanceType.JOINED) public abstract class BookKeepingParent implements Serializable { @Id protected Long Id; ... } @Entity public class Employee extends BookKeepingParent { private Stri

我有以下JPA2.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\u employee\u role\u id
引用的是
bookkeepingparent
表,而不是
role
表。我有一个很大的JPA实体继承权,我希望bookkeepingparent是其中大多数实体的超类。这主要是因为一些非常具体的Id生成策略和其他记账活动。这种设计有助于将所有这些簿记代码与函数代码分开,并让编写函数代码的程序员不必担心它

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

所以,以下是我的问题:JPA为什么要这么做?这是JPA的标准行为吗?(我正在使用EclipseLink)如果我手动更改DB模式,他们会遇到什么陷阱吗


这是我关于StackOverflow的第一个问题,我尽了最大努力寻找任何现有的答案。如果我错过了,我道歉。谢谢

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


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

比方说,JPA需要缓存来执行EntityManager.find()之类的操作。由于超类和子类的ID是相同的,所以使用哪个ID作为缓存的“键”并不重要。另外,关于DB约束,EclipseLink正在创建的约束有点“不准确”——使用外键引用超类允许在Employee的Role列中添加Role以外的表ID。因此,我的插入和更新肯定会符合约束条件,因为我的插入和更新比EclipseLink提出的要窄。所以我还是不明白他们为什么这么做。无论如何,谢谢。如前所述,主表是bookkeepingparent,因此默认值将始终指向EclipseLink中的该表。您可以通过在映射上定义joincolumn以转到辅助表来更改它,这将更改为DDL创建的约束-但它可能会有不命中缓存的限制。因此,更改DDL脚本可能比更改映射更好。如果我更改DDL脚本,使FK引用子类表,我将收到约束冲突错误。所以这不是一个解决方案。在我看来,这似乎是EclipseLink中的一个bug,因为它不能准确地表示对象关系。JPA指定子对象使用父对象的主键,并且引用必须始终指向主键,因此它根据规范工作。也就是说,它偶尔会出现,如图所示。children表也有一个主键。所以它可以很容易地被外键引用。我同意你的观点,FK应该引用子类。这似乎是EclipseLink中的一个bug,因为这样的映射显然是错误的,不能正确地反映关系。