Hibernate交换可嵌入类来迁移现有数据

Gar*_*son 6 hibernate migrate embeddable

我在这里不知所措,也许这是显而易见的,因为我的Hibernate专业知识比其他领域弱.

在遗留代码中有一个Hibernate @EntityFoo.其中一个属性是:

private OldBar bar = new OldBar();
Run Code Online (Sandbox Code Playgroud)

OldBar是一个@Embeddable使用单个列的类,foobar:

@Embeddable
public class OldBar {

  private String fooBar;

  @Column(length = 10, nullable = false)
  private String getFooBar() {
    return fooBar;
  }

  @SuppressWarnings("unused")
  private void setFooBar(String fooBar) {
    this.fooBar = fooBar;
  }
}
Run Code Online (Sandbox Code Playgroud)

最初的问题是我需要做一些事情OldBar.fooBar,但原始设计有局限性,并将此字段设为私有,阻止我对其进行子类化,因此我必须创建一个完整的其他类NewBar,以替换另一个类并获取访问权限私人领域.我认为既然NewBarEmbeddable有相同的@Column名称,我可以在课堂上换掉这个字段Foo:

private NewBar bar = new NewBar();
Run Code Online (Sandbox Code Playgroud)

我想这样做是因为我在foobar列中有现有数据,我想透明地使用这些数据NewBar而不是OldBar.

通过我看到的跟踪日志,在调用构造函数时Foo()创建了默认版本NewBar(),正如人们所期望的那样.然而,时间代码调用Foo.getBar(),由于某种原因,barnull!我假设Hibernate null出于某种原因设置它- 但为什么Hibernate不从foobar列中读取数据并创建实例NewBar?当我放回OldBar原位时为什么它再次亮相NewBar?当然,数据库本身没有任何内容表明哪些@Embeddable类映射到列,是吗?

更新:这变得陌生和陌生.有时我会让代码一夜之间,第二天就可以了!或者第二天它不起作用!刚才它没有用(也就是说,foobar属性被设置为null而不是数据库中的值),所以我创建了类ExactCopyOfOldBar并将它放在了位置OldBar.它工作正常!所以我切换回NewBar---只是撤消我的临时变化.它仍然有效,当它没有之前!是否存在某种缓存,其中Hibernate序列化值并且不从数据库中获取它们?这很奇怪.

更新:现在我再也无法NewBar上班了.我创建OtherBar,它基本上是相同的,NewBar除了它有一个不同的名称,我插入它,它工作,正确读取嵌入的字符串.我换回来了NewBar,我null又来了.到底是怎么回事?

注意Foo正在加载net.databinder.auth.hib.AuthDataApplication.getUser(String username),这很简单:

return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
    .add(Restrictions.eq("username", username)).uniqueResult();
Run Code Online (Sandbox Code Playgroud)

我一遍又一遍地验证了Foo(用户)表有一行包含正确的数据,最重要的是该foobar字段有数据.为什么Hibernate会给我Foo一个null foobar字段?为什么简单地从切换NewBarOtherBar让它再次开始工作?为什么它整天都在工作,然后在我一夜之间停止工作后停止工作?

Gar*_*son 1

这或许就是答案;我必须等待几天才能看到它是否确实解决了问题。实际上有两个部分。

首先,为了充分披露,我的NewBar类实际上是AbstractBar. 我最终想要拥有不同类型的可嵌入栏,因此我将其放置@EmbeddableAbstractBar级别上,而不是级别上NewBar,并将私有字段也放置foobar在级别上。AbstractBar有趣的是,这在某些时候是有效的。正如我提到的,有时我第二天回来时 Hibernate 不会加载该foobar字段。我不明白为什么它要么不一直有效,要么不一直有效。

其次,当我试图摆脱这个层次结构以消除问题的一个根源时,我混淆了,AbstractBarNewBar忘记将@EmbeddablefromAbstractBar调到NewBar,所以 Hibernate 没有看到这是一个可嵌入的类,并且不知道如何将字符串加载到NewBar没有@Embeddable指定的字段中。这就是为什么OtherBar(带@Embeddable注释)有效,但NewBar(不带@Embeddable注释)无效。我就明白这么多了。我不知道为什么 Hibernate 没有警告我它无法弄清楚如何加载字段。

总而言之,如果您将@Embeddable注释从类中删除,Hibernate 将不会加载可嵌入字段。至于最初的问题,我只能猜测,@Embeddable当尝试在类层次结构上使用它时,这是不稳定的,并且最好将所有可嵌入字段保留在可嵌入类中的一个级别。我希望这就是问题所在。我们明天看看它是否继续有效。