我在这里茫然不知所措,也许这很明显,因为我的Hibernate专业知识比其他领域薄弱。

在旧版代码中,有一个Hibernate @EntityFoo。其属性之一是:

private OldBar bar = new OldBar();
OldBar是使用单个列@Embeddablefoobar类:
@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;
  }
}

最初的问题是我需要对OldBar.fooBar进行操作,但是原始设计存在局限性,并且将该字段设置为私有(private),从而阻止了我对其进行子类化,因此我不得不创建另一个整个类NewBar,以替换另一个类并获得访问私有(private)字段。我以为,因为NewBar也是Embeddable,并且具有相同的@Column名称,所以我可以换掉Foo类中的字段:
private NewBar bar = new NewBar();

我之所以想这样做,是因为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();

我已经一遍又一遍地验证Foo(用户)表具有一行包含正确数据的数据,最重要的是foobar字段具有数据。为什么Hibernate给我返回一个带有Foo null字段的foobar?为什么简单地从NewBar切换到OtherBar使其重新开始工作?为什么一整天都可以正常工作,一整夜都无法工作?

最佳答案

这可能是答案。我将不得不等待几天,以查看它是否确实解决了该问题。实际上有两个部分。

首先,为了全面披露,我的NewBar类实际上是AbstractBar的子类。我最终希望拥有不同类型的可嵌入条形,因此我将@Embeddable放置在AbstractBar级别上,而不是NewBar级别,并将私有(private)foobar字段也放置在AbstractBar级别上。有趣的是,这在某些时候有效。正如我提到的,有时我第二天会回来,而Hibernate不会加载foobar字段。我不明白为什么它要么一直不工作,要么一直不工作。

其次,当我试图摆脱这种层次结构以消除问题的一个根源时,我将AbstractBarNewBar混为一谈,却忘记将@EmbeddableAbstractBar升级为NewBar,因此Hibernate并不认为这是一个可嵌入的类,并且不知道如何在不指定NewBar的情况下将字符串加载到@Embeddable字段中。这就是OtherBar(带有@Embeddable批注)而不是NewBar(没有@Embeddable批注)起作用的原因。我非常了解。我不知道为什么Hibernate不会警告我它无法弄清楚如何加载字段。

综上所述,如果您未将@Embeddable批注留在类中,则Hibernate将不会加载可嵌入字段。至于最初的问题,我只能猜测在尝试在类层次结构上使用@Embeddable时会出现问题,并且最好将可嵌入字段中的所有可嵌入字段都保留在一个级别。我希望那是问题。我们明天看它是否继续工作。

关于Hibernate换出可嵌入类以迁移现有数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10166656/

10-09 07:42