Pau*_*us2 3 java mysql concurrency jpa transactions
我在 SpringBoot 应用程序中使用 JPA 存储库 我有一个后台任务,定期将数据库中的某些元素设置为“就绪” 我还有一个用户可以调用的端点,并且可以修改同一个表的行之一。
有没有办法避免一个又一个取消对方的写入?以这个场景为例
Table:
Key
id name is_ready
Run Code Online (Sandbox Code Playgroud)
0)初始数据有一个键(1 no_name false)
1)后台任务启动,即将通过设置修改表Key
is_ready to true
Key key = repo.findKeyByIsReady(false)
key.setIsReady(true)
repo.save(key) <--- does NOT yet execute this
Run Code Online (Sandbox Code Playgroud)
2)用户调用api端点将密钥名称更改为“new_name”并完成
3)现在后台服务执行repo.save(key),最终数据为
1 no_name true
Run Code Online (Sandbox Code Playgroud)
代替
1 new_name true
Run Code Online (Sandbox Code Playgroud)
基本上后台任务已经覆盖了用户设置的键名
有没有办法避免这种情况?交易在这里有何帮助?
这通常通过额外的锁来解决:
您在第二个事务中检测到该行已被其他人更改。然后,您要么告诉用户并要求手动修复,要么尝试自动合并更改。
要实现它,您必须向表中添加额外的列 - 版本。然后,当更新行时,查询将如下所示:
UPDATE ..., version=old_version+1 WHERE id=old_id and version=old_version
Run Code Online (Sandbox Code Playgroud)
如果WHEREclose 找不到该行(因为其他人增加了版本),则更改的行数将为 0(JDBC 从 DB 获取此信息),并且 JPA 在这种情况下会抛出错误。
必须像@VersionJPA 中那样映射附加字段。
每次更新实体时,您都会使用构造:
select ... for update
Run Code Online (Sandbox Code Playgroud)
当第二个事务发出此类语句时,数据库会锁定该请求,直到第一个事务完成。如果在特定时间段内没有发生这种情况,您会收到 JPA 的异常。请参阅EntityManager#lock()方法以获取更多信息。
| 归档时间: |
|
| 查看次数: |
7556 次 |
| 最近记录: |