使用 @Version 列不允许 @ManyToOne 关系属性作为引用

发布于 2024-11-08 17:27:03 字数 846 浏览 4 评论 0原文

我正在使用休眠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 ) ;
throws an the famous "TransientObjectException: object references an unsaved transient..." exception. Surprisingly enough, if @Version @Column is removed or made @Transient, the above code would work perfectly fine. Any idea why i'm observing this behavior?

I'm using hibernate 3.6.3.Final. I have two relational entities A & B with a unidirectional ManyToOne defined as:


@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; }
....
}

Now suppose I have a B instance persistent in db already with pk id = 1, then doing the following operation:


A a = new A();
a.setRelationalB( new B( 1 ) );
session.saveOrUpdate( a ) ;


throws an the famous "TransientObjectException: object references an unsaved transient..." exception.
Surprisingly enough, if @Version @Column is removed or made @Transient, the above code would work perfectly fine.
Any idea why i'm observing this behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自由范儿 2024-11-15 17:27:03

问题是您没有使用数据库中的实体 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 与存储在数据库中的实体 B 相同。如果您想了解其背后的原因,请阅读工作单元模式。

尝试做类似的事情

B b = sessions.get(B.class, 1)
A a = new A();
a.setRelationalB( b );
session.saveOrUpdate( a ) ;

在另一点上:如果您想一次保存两个对象的新实例,那么您需要执行 级联

The problem is that you're not using the entity B which is in the database

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 ) ;

The problem is that hibernate cannot recognize that the new B you created is the same one as the one stored on the db. If you want to know the reason behind this, read about the Unit of Work pattern.

try doing something like

B b = sessions.get(B.class, 1)
A a = new A();
a.setRelationalB( b );
session.saveOrUpdate( a ) ;

On another point: if you want to save the new instances of both objects in one go, then you'll need to do a cascade.

演多会厌 2024-11-15 17:27:03

添加 @Version 列后,我也经常遇到“对象引用未保存的瞬态...”异常。 以下是我在我的案例中解决该问题的方法:

在我的案例中,问题出在外键上。编写代码的目的是不是加载引用的对象,而是创建一个新实例并设置主键,希望 Hibernate 能够找到真正的实例。我再说一遍:在 @Version 之前它工作得很好。

说明:

假设数据库中存在 ID 为 1 的类 B 对象,现在我们正在保存 A 的新实例。

  • 以前(不好)(添加 @Version 后出现异常):

    a.setB(new B(1));

    sf.getCurrentSession().save(a);

  • 已修复(运行良好) - 使用 @Version 没有问题:

    a.setB((B) sf.getCurrentSession().get(B.class, 1));

    sf.getCurrentSession().save(a);

在调试 Hibernate 时,我发现它会在 @Version 列存在时进行一些额外的检查。

因此,我相信遇到此错误的人要么没有加载他们试图引用的对象(无论如何这是一个更好的做法)要么他们真的试图保存<的新实例code>B(例如)但没有为其配置级联保存。

I had "object references an unsaved transient..." exception a lot after adding the @Version column, too. Here's how I solved it in my case:

In my scenario the problem was on the foreign keys. The code was written so that instead of loading the referred object it was creating a new instance and setting the primary key hoping that Hibernate would be able to find the real one. I repeat: it worked fine before the @Version thing.

Illustrating:

Consider an object of class B with id 1 exists on the database and now we're saving a new instance of A.

  • previously (no good) (was giving exception after @Version added):

    a.setB(new B(1));

    sf.getCurrentSession().save(a);

  • fixed (working well) - using @Version with no problems:

    a.setB((B) sf.getCurrentSession().get(B.class, 1));

    sf.getCurrentSession().save(a);

When debugging Hibernate I find out it does some extra checking when the @Version column is present.

So, I believe people having this error either aren't loading objects they're trying to make reference to (which is a better practice anyway) or they're really trying to save a new instance of B(for example) but didn't configure cascade save for it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文