Hibernate交换出可嵌入类以迁移现有数据
我在这里不知所措,也许这是显而易见的,因为我的Hibernate技能比其他领域弱 在遗留代码中有一个HibernateHibernate交换出可嵌入类以迁移现有数据,hibernate,migrate,embeddable,Hibernate,Migrate,Embeddable,我在这里不知所措,也许这是显而易见的,因为我的Hibernate技能比其他领域弱 在遗留代码中有一个Hibernate@实体classFoo。其特性之一是: private OldBar bar = new OldBar(); OldBar是一个@可嵌入的类,它使用单个列foobar: @Embeddable public class OldBar { private String fooBar; @Column(length = 10, nullable = false) p
@实体
classFoo
。其特性之一是:
private OldBar bar = new OldBar();
OldBar
是一个@可嵌入的
类,它使用单个列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
,但是最初的设计有一些限制,并且这个字段是私有的,阻止了我对它进行子类化,所以我必须创建一个完整的另一个类,NewBar
,来替换另一个类并访问私有字段。我想既然NewBar
也是可嵌入的
,并且具有相同的@列
名称,我可以交换类Foo
中的字段:
private NewBar bar = new NewBar();
我之所以想这样做,是因为我在foobar
列中有现有数据,并且我想将此数据透明地与NewBar
一起使用,而不是OldBar
通过跟踪日志,我看到当调用构造函数时,Foo()
被创建,其默认版本为NewBar()
。但是,当代码调用Foo.getBar()
时,由于某种原因bar
是null
!我假设Hibernate出于某种原因将其设置为null
——但是为什么Hibernate不从foobar
列读取数据并创建NewBar
的实例呢?为什么当我把OldBar
放回NewBar
的位置时,它又开始工作了?当然,数据库本身没有说明哪个@embeddeble
类映射到列,是吗
更新:这变得越来越陌生。有时我会让代码在一夜之间运行,第二天就可以了!或者第二天就不行了!刚才它不起作用(也就是说,foobar
属性被设置为null
,而不是数据库中的值),所以我创建了classExactCopyOfOldBar
,并将其放置在OldBar
的位置。它工作得很好!因此,我切换回NewBar
——只是撤销临时更改。它仍然有效,以前没有!是否存在某种缓存,Hibernate在其中序列化值而不从数据库获取它们?这很奇怪
更新:现在我再也不能让NewBar
工作了。我创建了OtherBar
,它基本上与NewBar
相同,只是它有一个不同的名称,我将它插入并正常工作,正确读取嵌入的字符串。我切换回NewBar
,再次得到null
。发生了什么事
请注意,Foo
是通过net.databinder.auth.hib.AuthDataApplication.getUser(字符串用户名)
加载的,这非常简单:
return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
.add(Restrictions.eq("username", username)).uniqueResult();
我反复验证了
Foo
(用户)表中有一行数据正确,最重要的是foobar
字段中有数据。为什么Hibernate会返回一个带有null
foobar
字段的Foo
?为什么简单地从NewBar
切换到OtherBar
会让它重新开始工作?为什么它工作了一整天,然后在我离开它过夜后就停止工作了?这可能就是答案;我得等几天,看看它是否真的解决了这个问题。实际上有两部分
首先,为了充分披露,我的NewBar
类实际上是AbstractBar
的一个子类。我最终希望有不同类型的可嵌入条,因此我将@embeddeble
放在AbstractBar
级别,而不是NewBar
级别,并将私有foobar
字段也放在AbstractBar
级别。有趣的是,这在某些时候奏效了。正如我提到的,有时候我第二天回来,Hibernate不会加载foobar
字段。我不明白为什么它不是一直工作就是一直不工作
其次,当我试图摆脱这种层次结构以消除问题的一个根源时,我将AbstractBar
和NewBar
混为一谈,但忘了将@embeddeble
从AbstractBar
提升到NewBar
,所以Hibernate没有看到这是一个可嵌入类,并且不知道如何在没有@embeddedable
指定的情况下将字符串加载到NewBar
字段中。这就是为什么OtherBar
(带有@embeddeble
注释)起作用,而不是NewBar
(没有@embeddeble
注释)。这一点我很理解。我不知道为什么Hibernate没有警告我它无法确定如何加载字段
总之,如果您将
@embeddeble
注释从类中移除,Hibernate将不会加载可嵌入字段。至于最初的问题,我只能猜测当试图在类层次结构上使用它时,@embeddeble
是不可靠的,最好将所有可嵌入字段保持在可嵌入类的一个级别上。我希望这就是问题所在。我们明天看它是否继续工作。我假设这是真的,但你没有说:Foo.bar
标记为@Embedded
?@Tim Pote:事实上,奇怪的是,在原始(工作)遗留代码中,它没有标记为@Embedded
。当我将表单OldBar
更改为NewBar
时,我尝试了@Embedded
和不使用@Embedded
的方法,但没有任何区别。@Tim Pote:我从休眠中了解到,“…如果属性的类型被注释为@Embedded,则映射为@Embedded”,因此从技术上讲@Embedded
部分是可选的。