Urb*_*leg 3 java concurrency spring hibernate jpa
所以我们正在开发一个高度并发的Web应用程序,这是一个非常大的多人游戏.
我们的服务器使用spring MVC,spring数据,MySQL和JPA.
我们现在讨论我们应该在并发方面使用的方法.
提出的一个建议几乎让我脱离了我的舒适区:
我习惯使用老式的orm风格:
@Transactional
@public void doSomeMagic() {
User user = userDao.findById(id);
user.setStuff(stuff);
...
}
Run Code Online (Sandbox Code Playgroud)
现在,提出的建议如下:
由于上述方法容易出现并发错误(并且可能通过锁定机制而减轻),为什么我们不使用SQL\JPQL更新呢?如果我们唯一的目标是更新其字段,为什么甚至打扰取用户?
我们可以这样做:
userDao.updatePlayer(stuffParameters); // "update Player p set stuffParameters...."
Run Code Online (Sandbox Code Playgroud)
现在,我对这种方法有一些疑问:
1)使用更新查询而不是仅通过ORM进行更新的做法有多常见?
2)这种方法的缺陷究竟是什么?
3)有没有混合解决方案?或者我没有谈到的另一种选择?
4)任何真正使用这种方法的人都能说出他得到的一些规则\实现吗?
谢谢!
首先,我想提一下,你的老式风格不应该使用save().附加实体自动持久化.这个save()电话没用.对附加实体所做的每个更改都将在提交时(或更早)保留.
我还想指出,与使用更新查询的方法相比,此方法不再存在并发问题.相反:如果使用乐观锁定(使用@Version),旧式的执行方式比更新查询方法(它只是更新状态而不管某些并发事务是否也更新它)的并发性问题更少.
关于你的不同点:
不常见,因为这比仅修改实体并让JPA处理更新查询要麻烦得多.处理复杂的用例也要复杂得多,并且使代码看起来像JDBC代码,JPA首先允许这样做.
如果您使用更新查询,则会绕过乐观锁定的缺陷,就像第一级缓存一样.因此,如果您已加载实体并使用更新查询来更新其状态,则加载的实体仍将保持旧状态.
您可以一起使用这两种方法.请注意我在第2点提到的陷阱.
更新查询是有意义的,特别是如果目标是一次更新许多实体.如果您已经证明存在性能问题,我只会降级到这种方法,并且可以通过使用此方法解决此性能问题.否则,它只是过早优化,具有高生产率和稳健性成本.
| 归档时间: |
|
| 查看次数: |
598 次 |
| 最近记录: |