Jpa 重头戏1.2.3框架-提交事务的正确方式
我们有一个HTTP端点,需要很长时间才能运行,用户也可以并发调用它。作为该请求的一部分,我们在同步块内更新模型,以便其他(可能并发的)请求获取该更改 例如 之所以使用同步块,是为了确保即使是并发请求也能获取最新状态。但是,在请求完成之前,底层JPA不会提交我的更改(m.save())。因为这是一个长时间运行的请求,所以我不想等到请求完成后再等待,而是希望确保其他呼叫者收到状态更改的通知。我试图在m.save()之后调用“m.em().flush();JPA.em().getTransaction().commit();”,但这会使事务无法作为同一请求的一部分用于后续操作。我可以只给出“JPA.em().getTransaction().begin();”并让Play从那时起处理事务吗?如果不是,处理这个用例的最佳方法是什么 更新: 根据回复,我修改了代码如下:Jpa 重头戏1.2.3框架-提交事务的正确方式,jpa,playframework,Jpa,Playframework,我们有一个HTTP端点,需要很长时间才能运行,用户也可以并发调用它。作为该请求的一部分,我们在同步块内更新模型,以便其他(可能并发的)请求获取该更改 例如 之所以使用同步块,是为了确保即使是并发请求也能获取最新状态。但是,在请求完成之前,底层JPA不会提交我的更改(m.save())。因为这是一个长时间运行的请求,所以我不想等到请求完成后再等待,而是希望确保其他呼叫者收到状态更改的通知。我试图在m.save()之后调用“m.em().flush();JPA.em().getTransaction
MyModel m = null;
synchronized (lockObject) {
m = MyModel.findById(id);
if (m.status == PENDING) {
m.status = ACTIVE;
} else {
//render a response back to user that the operation is not allowed
}
m.save(); //Is not expected to be called unless we set m.status = ACTIVE
}
new MyModelUpdateJob(m.id).now();
在我的工作中,我有以下几行:
doJob() {
MyModel m = MyModel.findById(id);
print m.status; //This still prints the old status as-if m.save() had no effect...
}
我遗漏了什么?把你的更新代码放在一个工作电话里
new MyModelUpdateJob(id).now().get();
因此,更新将在作业结束时提交的另一个事务中完成哎哟,一旦您添加更多播放服务器,您就会遇到麻烦。您可能希望在示例中使用乐观锁定,或者我建议不要使用悲观锁定 但是,看看你的代码,也许可以读一下这篇文章。我不确定在这种情况下你是否需要一个同步块……试着去做幂等的 就你而言,如果 1.用户1和用户2都调用该方法,该方法处于挂起状态,然后它变为活动(幂等) 如果用户1或用户2赢了,那么不管怎样,这就像你有了同步块一样 不过,我相信这里没有展示一个更复杂的场景,但请阅读这篇基于流沙的文章,因为它确实改变了传统的思维方式,也改变了谷歌、亚马逊和超大规模系统的运作方式 跨play服务器的分布式事务的另一个选择是zookeeper,大型nosql人员使用它,但仅作为最后手段;);) 后来,,
院长谢谢。我已经根据你的回复更新了我的帖子。简言之,作业似乎没有获得行的更新,并且仍然看到旧状态。@Ananth您检查了吗?在我看来,如果您还告诉控制器方法您希望等待作业完成,则双作业设置应该可以工作。对播放控制器的调用是一个事务。因此,当http请求/响应完成时,您将看到控制器中所做的修改。在您的工作中,您无法看到在控制器中完成的事情,因为该方法尚未完成。您必须基于此重新思考代码。你还必须注意迪恩说的话。出于业务目的使用同步块不是一种好的做法,而且这不会扩展
new MyModelUpdateJob(id).now().get();