我必须维护一些用于管理某些数据库表的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以便一切继续工作?
答案 0 :(得分:2)
如果你对桌面设计没有任何影响,未来的设计会让人大吃一惊,情况看起来很惨淡:)
但也许您仍然可以使用您的实体进行微小更改。好消息是除了SINGLE_TABLE
- JOINED
和TABLE_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标准中包含这个: - (。