【发布时间】:2013-11-12 14:27:18
【问题描述】:
我有一个 POJO(在此示例中为 Myclass),我在我的应用程序中保留/更新/删除它。
我使用侦听器类检测对该对象的更改,然后在侦听器类中将更改保存到另一个表。
Here is my class (dummy example) :
EntityListeners({MyListener.class})
class MyClass {
String name;
String surname;
/*...getters...setter..etc */
public void save() {
JPA.em().persist(this);
return this;
}
public void update() {
JPA.em().merge(this);
}
}
class MyListener {
@preUpdate
public void preUpdate() {
/*...some logic to save the changes irrelevant*/
someAuditObj.createWithData(.......);
someAuditObj.save();
}
}
我正在使用 play framework v2.1.3 构建我的网络应用程序,所有这些都运行良好,我真的很高兴它的运行方式。
今天我将游戏框架更新为更新版本v2.2.1。
并且由于某种原因,当MyClass 的实例发生更改并且侦听器获取更改并尝试保存更改时,事务失败,我在日志中找到了这个:
Caused by: java.lang.RuntimeException: No EntityManager bound to this thread
所以我花了一段时间才弄清楚由于某种原因事务没有传播到侦听器,然后我尝试了一些方法来修复它(侦听器类):
@preUpdate
public void preUpdate() {
/*...some logic to save the changes irrelevant*/
JPA.withTransaction(new F.Callback0() {
@Override
public void invoke() throws Throwable {
someAuditObj.createWithData(.......);
someAuditObj.save();
});
}
所以这修复了它,它像以前一样工作,没有问题。
我的问题是:
- 为什么它以前没有手动干预早期版本的游戏框架的交易就可以工作
- 有没有更好的方法可以更优雅地实现相同的目标(我不确定这个词是否合适)?
更新
这是我的控制器方法:
@Transactional
public Result updateName(Long id, String name){
MyClass c = MyClass.findById(id);
c.setName(name);
c.update();
return ok();
}
所以事务应该传播到所有方法,对吗?但为什么不去倾听呢?
我的估计是这样的:
如果一个方法有@Transactional注解,那么内部发生的所有调用都应该在一个事务中?
【问题讨论】:
-
你能发布你的控制器代码来调用你的更新方法吗?异步操作不一定在同一个线程上运行。这将解释您看到的错误消息。我相信您现在设置它的方式是实现交易保证的最佳方式。
-
我猜问题是
preUpdate在不同的线程中运行,这听起来像是一个错误。您是否使用不同的回调(例如 prePersist)得到类似的错误?我意识到 prePersist 不适合您的用例。
标签: java hibernate jpa playframework playframework-2.0