1

我必须维护一些用于管理一些数据库表的 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 以便一切继续工作?

4

2 回答 2

2

如果您对桌子设计完全没有影响,那么未来的设计会让人大吃一惊,那么情况看起来很黯淡:)

但也许您仍然可以使用您的实体进行细微的更改。好消息是 JPA 除了SINGLE_TABLE-JOINEDTABLE_PER_CLASS.

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

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将是您在评论中谈论的另一张桌子。

于 2013-01-21T15:48:27.630 回答
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 标准中:-(。

于 2013-01-21T15:58:25.347 回答