2012-03-01 55 views
3

我想优化我的数据库表。但是我对Hibernate/JPA的理解不够,现在帮助不大。如何将继承策略与多个子类层结合使用

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

ParentClass 
    SubClass1 
    SubSubClass1 
    SubSubClass2 
    SubSubClass3 
    SubSubClass4 
    SubClass2 
    SubSubClass5 
    SubSubClass6 

所有类包含字段。大约50%的所有字段都在ParentClass中。 40-50%属于SubClass1级别,0-10%属于SubSubclass级别。许多SubSubClass *类都是空的,但对于识别类型是必需的。

TRY 1:

大二我们首先做的是在父类上使用TABLE_PER_CLASS策略。这导致巨大的表的量:

SubSubClass1 
SubSubClass2 
SubSubClass3 
SubSubClass4 
SubSubClass5 
SubSubClass6 

这是不很凉爽,因为在这些表中的所有列的50%的所有表和其他剩下的是3-4表之间共享之间共享。

TRY 2:

我们改变了策略,以SINGLE_TABLE。

结果表只是一个大的“ParentClass”表。但是由于在所有子类中只有大约50%的列是共享的,因此很多字段必须设置为Null,这不够性感。

TRY 3:

下一个尝试是将逐步转向以 “SINGLE_TABLE” 策略混合TABLE_PER_CLASS战略。我决定不使用JOIN TABLES作为一种策略,因为我必须有许多小的子类,这些子类会导致创建许多许多带有一个或两个列的小表。

所以,我如下回答这样一个问题:How to mix inheritance strategies with JPA annotations and Hibernate?

我现在希望把所有的值从父类中的一个表,然后从第一分段到一个表为他们每个人的所有值。这将导致在这样的模式:

ParentClass 
- SubClass1 
- SubClass2 
- SubClass3 

这里是我的代码:

@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; 
} 

里面居然作品相当不错的。但我的问题开始了:

首先我在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 

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

第二个问题是,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) 

它加入我所用的@SecondaryTable标注在子类中,每次同一个表。它一次又一次地加入。我看了一下甲骨文的解释计划,告诉我这个计划会自动优化,如果我会优化它的话。但不管怎么说。真奇怪。

问题:

如何防止从创建相同的约束多次休眠?我认为这也会解决连接问题。或者应该停止尝试这样做,并有另一种方式?

回答

2

我想你应该真的使用SINGLE_TABLE策略。共享列的50%真的没有那么糟糕,特别是如果你知道这个数字不会随着时间而减少(我的意思是你认为有一天这个表格中会有500列,只有40列被分享?),以及如果您要针对根实体运行大量查询,并始终与其他策略进行多次连接。

在工作中我们刚刚讨论过这个问题。 选择了SINGLE_TABLE策略是因为我们认为列数不会爆炸,并且我们可能只以5%的共享属性结束:(所以我认为它适用于您的情况,但要小心并考虑数据的方式

编辑:因为不可能混用策略而且你不需要很多表: 如果你有140个子实体和50%的共享属性,你应该真的使用SINGLE_TABLE策略! !!!!!

+0

我们结束了使用SINGLE_TABLE策略。分析SQL Querys显示了巨大的效率收益。单个表格会导致查询的成本为6.每个额外连接的表格都会增加1个成本。有了完整的联合表格布局,我们最终将获得超过150个表格,从而产生160个成本。这再次是单桌会议的26倍。我们认为我们会混合一些辅助表来优化代码的某些部分。测试表明,这是非常整洁,不会导致许多问题,除了我在我的问题中提到的问题(这是可以修复或可以忽略的) – user932708 2012-03-02 16:02:18

0

为什么不在父类上使用策略JOINED?你仍然有很多表,但没有多余的属性。

+0

您刚刚提到我的答案:对很多表格而言,数据库需要被其他未使用Java数据模型的技术所使用,为此我们的目标是将表格数量减少为一个公平的计数在一个表格方法和JOINED之间做法。一个表将导致1个表。 JOINED会导致大约140个表格。我们的计划方法将导致约1主表+6子表 – user932708 2012-03-01 14:44:04

8

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

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

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

+0

呃..不幸的是,这个答案是正确的:) – user932708 2012-03-02 16:00:06