用SQL替换JPA / Hibernate DiscriminatorColumn

时间:2013-01-21 15:39:36

标签: java hibernate jpa

我必须维护一些用于管理某些数据库表的JPA / Hibernate代码。我有这样的类层次结构:

@Entity
@Table(name="table_name")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="column_name", discriminatorType=DiscriminatorType.STRING)
public abstract class AbstractBaseClass {...}

@Entity
@DiscriminatorValue("N")
public class SubClass1 extends AbstractBaseClass { ...}

@Entity
@DiscriminatorValue("Y")
public class SubClass2 extends AbstractBaseClass { ...}

这一切都运行正常,但数据库正在重新设计,将删除歧视列,并且记录的类型将由SQL查询确定。这种重新设计不是我的想法,我无法控制数据库结构。由于现有的代码库,更改Java层次结构也是不切实际的。我可以使用什么代替DiscriminatorColumn / DiscriminatorValue以便一切继续工作?

2 个答案:

答案 0 :(得分:2)

如果你对桌面设计没有任何影响,未来的设计会让人大吃一惊,情况看起来很惨淡:)

但也许您仍然可以使用您的实体进行微小更改。好消息是除了SINGLE_TABLE - JOINEDTABLE_PER_CLASS之外,JPA还提供了2个继承映射模型。

加入:你最终会得到三个表,每个表一个,包括抽象表。这些表将包含各个类中包含的属性。要访问不同类型,提供者必须访问(并加入)不同的表,因此不需要鉴别器列。

TABLE_PER_CLASS:您将拥有两个表,每个表对应一个具体的子类。它们中的每一个都将映射抽象父类的所有属性以及它们自己的属性。和以前一样,提供者将使用单独的表,因此不需要鉴别器。

要进行转换,您必须更改行

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@Inheritance(strategy=InheritanceType.JOINED)

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

JPQL查询的好处是它们根本不需要改变。只需使用JPQL TYPE关键字,提供者就可以完成所有映射。

编辑:还有一件事 - 如果您必须处理单个表但没有鉴别器,并且类型将由连接确定,您可以使用像这样的JPQL构造函数表达式:

SELECT NEW com.example.SubClass1(e.name, e.address) FROM CommonSurrogateEntity e, TypeHintEntity t WHERE t.type = e.foreignKey

CommonSurrogateEntity将是一个假类,映射整个公共表。 TypeHintEntity将是您在评论中谈论的另一张表。

答案 1 :(得分:1)

如果可以使用简单的SQL公式确定鉴别器,则可以使用特定于hibernate的@DiscriminatorFormula扩展名:

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@org.hibernate.annotations.DiscriminatorFormula("(CASE WHEN ... THEN 'SubClass1' ELSE 'SubClass2' END)")
public abstract class AbstractBaseClass {

}

不知道为什么他们没有在JPA标准中包含这个: - (。