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

发布于 2024-09-12 03:41:27 字数 1010 浏览 2 评论 0原文

我有一个使用 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;
}

此后我添加了 A 的一个子类,称为 B:

@Entity
public class B extends A {
  public String description;
}

添加 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)

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

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

I have an application using Hibernate for data persistence, with Spring on top (for good measure). Until recently, there was one persistent class in the application, A:

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

I have since added a subclass of A, called B:

@Entity
public class B extends A {
  public String description;
}

After adding B, I could now not load A's. The following exception was thrown:

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)

I added the following annotation and property to B, and it seems to have solved the problem. Is this the right way to solve the issue?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暗地喜欢 2024-09-19 03:41:27

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

具有以下数据库表示形式:

ID  NAME
--  ----
 1   foo
 2   bar

此后我添加了 A 的子类,称为 B (...)

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

该表变为:

ID  NAME DTYPE
--  ---- -----
 1   foo  NULL
 2   bar  NULL

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

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

确实,因为现有值在鉴别器列中具有空值,所以提供程序不知道要实例化哪个子类。

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

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

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

UPDATE A SET DTYPE='A' WHERE DTYPE=NULL

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

(...) Until recently, there was one persistent class in the application, A:

With the following database representation:

ID  NAME
--  ----
 1   foo
 2   bar

I have since added a subclass of A, called B (...)

And you didn't specify the Inheritance annotation so the SINGLE_TABLE mapping strategy is used. And In this strategy, all the classes in a hierarchy are mapped to a single table. The table has a column that serves as a “discriminator column”, that is, a column whose value identifies the specific subclass to which the instance that is represented by the row belongs.

The table then became:

ID  NAME DTYPE
--  ---- -----
 1   foo  NULL
 2   bar  NULL

Where DTYPE is the default name of column to be used for the discriminator.

After adding B, I could now not load A's. The following exception was thrown (...)

Indeed, because existing values have a null value in the discriminator column, the provider doesn't know what subclass to instantiate.

I added the following annotation and property to B, and it seems to have solved the problem. Is this the right way to solve the issue?

That's one way but it is intrusive (your entities shouldn't be aware of the dtype column) and Hibernate specific. In other words, it's a hack.

For me, the "right" way to solve this would be to update the DTYPE column of existing A records to set the value to 'A' (with Hibernate, the value defaults to the entity name):

UPDATE A SET DTYPE='A' WHERE DTYPE=NULL

This way, Hibernate would be able to load them properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文