使用DiscriminatorFormula迁移Hibernate数据库是不好的做法吗?

Arm*_*and 5 java orm persistence hibernate table-per-hierarchy

我有一个使用Hibernate进行数据持久化的应用程序,其中Spring处于最佳状态(很好的衡量标准).直到最近,应用程序中还有一个持久化类,A:

@Entity
public class A {
  @Id
  @Column(unique = true, nullable = false, updatable = false)
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  public String name;
}
Run Code Online (Sandbox Code Playgroud)

我已经添加了A的子类,称为B:

@Entity
public class B extends A {
  public String description;
}
Run Code Online (Sandbox Code Playgroud)

添加B后,我现在无法加载A. 抛出以下异常:

class org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException :: Object with id: 1 was not of the specified subclass: A (Discriminator: null); nested exception is org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: A (Discriminator: null)
Run Code Online (Sandbox Code Playgroud)

我将以下注释和属性添加到B,它似乎已经解决了问题.这是解决问题的正确方法吗?

...
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'A' ELSE dtype END)")
public class A {
    private String dtype = this.getClass().getSimpleName();
    ...
Run Code Online (Sandbox Code Playgroud)

Pas*_*ent 2

\n

(...) 直到最近,应用程序中还有一个持久类 A:

\n
\n\n

具有以下数据库表示:

\n\n
ID  NAME\n--  ----\n 1   foo\n 2   bar\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

我添加了 A 的一个子类,称为 B (...)

\n
\n\n

并且您没有指定注释,Inheritance因此SINGLE_TABLE使用映射策略。在此策略中,层次结构中的所有类都映射到单个表。该表有一列用作 \xe2\x80\x9c 鉴别器列\xe2\x80\x9d,即该列的值标识该行所表示的实例所属的特定子类。

\n\n

那么该表就变成了:

\n\n
ID  NAME DTYPE\n--  ---- -----\n 1   foo  NULL\n 2   bar  NULL\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中 DTYPE 是用于鉴别器的列的默认名称。

\n\n
\n

添加 B 后,我现在无法加载 A 的。抛出了以下异常(...)

\n
\n\n

事实上,由于现有值在鉴别器列中具有空值,因此提供程序不知道要实例化哪个子类。

\n\n
\n

我在B中添加了以下注释和属性,似乎已经解决了问题。这是解决问题的正确方法吗?

\n
\n\n

这是一种方式,但它是侵入性的(您的实体不应该知道该dtype列)并且是 Hibernate 特定的。换句话说,这是一个黑客行为。

\n\n

对我来说,解决这个问题的“正确”方法是更新DTYPE现有 A 记录的列以将值设置为\'A\'(使用 Hibernate,该值默认为实体名称):

\n\n
UPDATE A SET DTYPE=\'A\' WHERE DTYPE=NULL\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样,Hibernate 将能够正确加载它们。

\n