<>前言

在JPA中,使用save方法时是这样的:如果我们save的对象指定了主键,那么会根据主键先进行一次查询,如果查询记录不存在则执行insert语句,如果查询记录存在则执行update语句。

<>问题现象

业务场景是这样的:当某个用户钱包流水发生变化时,我们会先查询用户钱包是否存在(新注册的用户一开始没有钱包),如果存在则直接更新钱包余额,并添加一条流水,如果用户钱包不存在,则新生成钱包,再更新钱包余额,最后添加流水。

当同一个用户同时产生多条流水时,现在的流程则可能出现问题。

<>伪代码
// 查询用户钱包是否存在 User u = select(userId); if(u == null){ // 不存在则生成钱包,初始化钱包余额为0 jpa
.save(u); } // 添加流水 addFlow(u); // 更新钱包余额 update(u);
<>问题分析

问题就发生在当第一个线程save成功后,第二个线程再执行时,save就会变成update,并且会覆盖第一个线程所执行的操作。

<>解决方法

只要让自定义save方法,就是insert操作就可以了,当第2个线程save时,会报主键冲突,然后第2个线程再重试一次,再次查询钱包是否存在时,就可以查询到了,然后就不用再生成钱包了,直接更新余额即可(更新余额幂等性)。

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信