方法一、
通过在数据库中加入version 字段,解决并发时 进行“回显修改” 操作时,
对不同用户对同一数据进行同时修改时,后面的修改会覆盖前面的修改的问题。
出现问题的情况描述和问题解决概述:
这个截图的源文件链接:有道云笔记
一些说明:
1、已经添加事务了,为什么不能解决,还要加这个version 字段?
事务对并发的解决主要在,事务的隔离级别(未提交读,提交读,可重复读,序列化)。他解决的是一个事务执行时的并发问题。但回显修改不在一个事务中。
2、这样完全解决了吗?
并没有,这里加入version 字段解决的只是回显到表单,到提交后执行到 if(newVersion == oldversion) 的问题。 当两个操作,都进入到if(newVersion == oldversion) { } 代码块里。提交有先后就又出现问题了。
但我们知道并发中出现的问题概率,是和执行一个操作的时间有关的,在这个问题里,“用户查看表单,再点击修改的时间”,和”程序进入这个if代码块内后程序的执行时间”明显站据了大头(90%)。
也就是说加入version 解决了我们的大问题。
3、怎样完全解决?
很简单,在使用version 的基础上给 这段修改代码方法加锁。保证同一时间只有一个人能提交修改,这就解决了剩下那段的问题。
4、有没有其他的方法?
有!(下面的示例代码有局限性)
方法二、
就是你提交更新的时候,仅更新你修改了的项。这样的话就不会覆盖别人的东西了。
1)把原来的回显的时候的对象放入session 中。
2)把修改提交后得到新对象,和放在session 中的老对象,传入service
3)在service层中进行对比,没有改过的项置为null ,改过的保留改后的。
比较不同的工具代码
4、在mapper层中通过动态sql(mybatis) ,按需更新。
<update id="updateTargetPhone" parameterType="TargetPhone">
UPDATE tb_target_phone
<set>
<if test="phone.name != null">
name = #{phone.name},
</if>
<if test="phone.remainMoney != null">
remain_money = #{phone.remainMoney},
</if>
<if test="phone.smsSend != null">
sms_send = #{phone.smsSend}
</if>
</set>
WHERE id = #{phone.id}
</update>