我在这里茫然不知所措,也许这很明显,因为我的Hibernate专业知识比其他领域薄弱。
在旧版代码中,有一个Hibernate @Entity
类Foo
。其属性之一是:
private OldBar bar = new OldBar();
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;
}
}
最初的问题是我需要对
OldBar.fooBar
进行操作,但是原始设计存在局限性,并且将该字段设置为私有(private),从而阻止了我对其进行子类化,因此我不得不创建另一个整个类NewBar
,以替换另一个类并获得访问私有(private)字段。我以为,因为NewBar
也是Embeddable
,并且具有相同的@Column
名称,所以我可以换掉Foo
类中的字段:private NewBar bar = new NewBar();
我之所以想这样做,是因为
foobar
列中有现有数据,并且我想将此数据与NewBar
而不是OldBar
透明地一起使用。通过跟踪日志,我已经看到创建了
Foo()
,其默认版本为NewBar()
,这是在调用构造函数时所期望的。但是,由于时间码调用Foo.getBar()
,出于某种原因bar
是null
!我假设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
字段。我不明白为什么它要么一直不工作,要么一直不工作。
其次,当我试图摆脱这种层次结构以消除问题的一个根源时,我将AbstractBar
和NewBar
混为一谈,却忘记将@Embeddable
从AbstractBar
升级为NewBar
,因此Hibernate并不认为这是一个可嵌入的类,并且不知道如何在不指定NewBar
的情况下将字符串加载到@Embeddable
字段中。这就是OtherBar
(带有@Embeddable
批注)而不是NewBar
(没有@Embeddable
批注)起作用的原因。我非常了解。我不知道为什么Hibernate不会警告我它无法弄清楚如何加载字段。
综上所述,如果您未将@Embeddable
批注留在类中,则Hibernate将不会加载可嵌入字段。至于最初的问题,我只能猜测在尝试在类层次结构上使用@Embeddable
时会出现问题,并且最好将可嵌入字段中的所有可嵌入字段都保留在一个级别。我希望那是问题。我们明天看它是否继续工作。
关于Hibernate换出可嵌入类以迁移现有数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10166656/