如何将继承策略与多个子类层结合使用

use*_*708 4 orm annotations hibernate jpa hierarchy

我试图优化我的数据库表.但是我对Hibernate/JPA缺乏了解并没有多大帮助.

我有一个Java对象模型,看起来或多或少像这样:

ParentClass
  SubClass1
    SubSubClass1
    SubSubClass2
    SubSubClass3
    SubSubClass4
  SubClass2
    SubSubClass5
    SubSubClass6
Run Code Online (Sandbox Code Playgroud)

所有类都包含Fields.大约50%的所有字段都在ParentClass中.40-50%属于SubClass1级别,0-10%属于SubSubclass级别.许多SubSubClass*类都是空的,但是需要用于标识Type.

尝试1:

所以.我们首先做的是在Parentclass上使用TABLE_PER_CLASS策略.这导致了大量的表:

SubSubClass1
SubSubClass2
SubSubClass3
SubSubClass4
SubSubClass5
SubSubClass6
Run Code Online (Sandbox Code Playgroud)

这不是很酷,因为这些表中所有列的50%在所有表之间共享,而其他Rest在3-4个表之间共享.

尝试2:

我们将策略更改为SINGLE_TABLE.

结果表只是一个大的"ParentClass"表.但由于所有列中只有大约50%在所有子类之间共享,因此许多字段必须设置为Null,这不是那么性感.

尝试3:

下一步尝试将TABLE_PER_CLASS策略与"SINGLE_TABLE"策略混合.我决定不使用JOIN TABLES作为策略,因为我必须使用许多小的子类,这会导致创建许多包含一个或两个Columns的小表.

所以,我在这个问题中回答了以下问题:如何将继承策略与JPA注释和Hibernate混合使用?

我现在想要将ParentClass中的所有值放在一个表中,将第一个SubLevel中的所有值放入一个表中.这应该导致这样的Schema:

ParentClass
 - SubClass1
 - SubClass2
 - SubClass3
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

@MappedSuperclass
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class ParentClass {
  private String value1;
}

@MappedSuperclass
@SecondaryTable(name = "SubClass1")
public abstract class SubClass1 extends ParentClass {
  @Column(table = "SubClass1")
  private String value11;
}

@MappedSuperclass
@SecondaryTable(name = "SubClass2")
public abstract class SubClass2 extends ParentClass {
  @Column(table = "SubClass2")
  private String value12;
}


@Entity
@SecondaryTable(name = "SubClass1")
public abstract class SubSubClass1 extends SubClass1 {
  @Column(table = "SubClass1")
  private String value111;
}

@Entity
@SecondaryTable(name = "SubClass2")
public abstract class SubSubClass2 extends SubClass2 {
  @Column(table = "SubClass2")
  private String value121;
}
Run Code Online (Sandbox Code Playgroud)

哪个实际上运作得很好.但是我的问题开始了:

首先,我在SchemaUpdate期间遇到以下错误.

Unsuccessful: alter table schema.SubClass1 add constraint AAAAAAA36D68C4 foreign key (id) references schema.ParentClass
ORA-02275: such a referential constraint already exists in the table

Unsuccessful: alter table schema.SubClass2 add constraint AAAAAAA36D68C4 foreign key (id)  references schema.ParentClass
ORA-02275: such a referential constraint already exists in the table
Run Code Online (Sandbox Code Playgroud)

我认为这些错误是由于我在多个级别上不止一次使用SecondaryTables造成的.每次我使用它们时,都会创建另一个约束.这当然不起作用,因为约束已经存在.

第二个问题是,如果它应该从所有这些表中获取数据,Hibernate会变得疯狂:

select
    * 
from
    ( select
        parentclass0_.value1 as value1_1_,
        parentclass0_1_.value11 as erste1_3_,
        parentclass0_1_.value111 as value1113_3_,
        parentclass0_2_.value12 as value122_3_,
        parentclass0_2_.value121 as value1214_3_,
        parentclass0_.DTYPE as DTYPE2_ 
    from
        schema.parentclass parentclass0_ 
    left outer join
        schema.subclass1 parentclass0_1_ 
            on parentclass0_.id=parentclass0_1_.id 
    left outer join
        schema.subclass1 parentclass0_2_ 
            on parentclass0_.id=parentclass0_2_.id 
    left outer join
        schema.subclass1 parentclass0_3_ 
            on parentclass0_.id=parentclass0_3_.id 
    left outer join
        schema.subclass2 parentclass0_4_ 
            on parentclass0_.id=parentclass0_4_.parentclass_id 
    left outer join
        schema.subclass1 parentclass0_5_ 
            on parentclass0_.id=parentclass0_5_.id 
    left outer join
        schema.subclass1 parentclass0_6_ 
            on parentclass0_.id=parentclass0_6_.id ) 
Run Code Online (Sandbox Code Playgroud)

每次我在子类中使用@SecondaryTable注释时,它都会加入同一个表.它一次又一次地加入它.我看了一下Oracle的解释计划,它告诉我这个计划会自动优化,如果我要优化它,我将会使用它.但无论如何.真奇怪.

问题:

如何防止Hibernate多次创建相同的约束?我认为这也可以解决加入问题.或者应该停止尝试这样做,还有另一种方法吗?

Dat*_*eus 9

从纯粹的JPA角度来看,您不能在继承树中混合策略.引用JPA规范(11.1.20)

继承注释定义了用于实体类层次结构的继承策略.它在实体类上指定,该实体类是实体类层次结构的根.本规范不要求支持继承策略的组合.可移植应用程序应仅在实体层次结构中使用单个继承策略.

JDO是唯一允许您在树下定义不同策略的持久性规范.