我正在使用hibernate 3.6.3.Final。我有两个关系实体A& B使用单向ManyToOne定义为:
@Entity public class A {
...
@Version @Column ( name = "ChangeNumber" )
public Long getVersion() { return version; }
@ManyToOne @JoinColumn( name = "B_ID" )
public B getRelationalB() { return relationalB; }
...
}
@Entity public class B {
@Version @Column ( name = "ChangeNumber" )
public Long getVersion() { return version; }
....
}
现在假设我在db中已经有一个B实例,pk id = 1,然后执行以下操作:
A a = new A();
a.setRelationalB( new B( 1 ) );
session.saveOrUpdate( a ) ;
抛出着名的“TransientObjectException:object引用未保存的瞬态...”异常。
令人惊讶的是,如果@Version @Column被删除或制作@Transient,上面的代码将完全正常。
知道我为什么观察这种行为吗?
答案 0 :(得分:0)
问题是您没有使用数据库中的实体B
A a = new A();
// you're instantiating a "new" B with id 1, this is not the same
// as the "object" you have in the database.
a.setRelationalB( new B( 1 ) );
session.saveOrUpdate( a ) ;
问题在于,hibernate无法识别您创建的新B与存储在db上的新B相同。如果您想知道背后的原因,请阅读Unit of Work模式。
尝试做类似
的事情B b = sessions.get(B.class, 1)
A a = new A();
a.setRelationalB( b );
session.saveOrUpdate( a ) ;
另一点:如果你想一次保存两个对象的新实例,那么你需要做cascade。
答案 1 :(得分:0)
在添加@Version列之后,我有很多“对象引用未保存的瞬态......”异常。 以下是我在案例中解决的问题:
在我的场景中,问题出现在外键上。编写代码是为了而不是加载引用的对象,而是创建一个新实例并设置主键,希望Hibernate能够找到真正的实例。我再说一遍:它在@Version之前运行良好。
龙虎斗:
考虑数据库中存在标识为B
的类1
的对象,现在我们正在保存A
的新实例。
之前(不好)(在@Version添加后发出异常):
a.setB(new B(1));
sf.getCurrentSession()保存的(a);
修复(运作良好) - 使用@Version没有问题:
a.setB((B)sf.getCurrentSession()。get(B.class,1));
sf.getCurrentSession()保存的(a);
调试Hibernate时,我发现当@Version列存在时会进行一些额外的检查。
所以,我相信有这个错误的人或者没有加载他们试图引用的对象(无论如何这是一个更好的做法)或他们真的想要保存一个新的B
的实例(例如),但没有为它配置级联保存。