update 大家会允许这样写吗?

199 天前
 Niner
User u = userMapper.selectOne(id);
u.setName(myname);
u.setAge(myAge);
userMapper.updateById(u);

我看工作里面很多代码都是这样更新的,虽然方便但是有并发问题,大佬们 cr 遇到会打回去吗?

7722 次点击
所在节点    Java
73 条回复
kanepan19
199 天前
看场景,订单这样去更新要被批。
用户这样更无所谓。
ncbdwss
199 天前
绝对不允许。
KongLiu
199 天前
并发问题,建议加上乐观锁
SingeeKing
199 天前
不懂 java ,但为啥这样会有并发问题?按我的理解 u 是 select 返回的,updateById 的过程才会创建 transaction 并 commit ,理论上 u 不共享不会出并发问题?
MooRider
199 天前
@SingeeKing #4 第一个请求还没完成的时候第二个请求进来了, 由于一些原因导致第二个请求比第一个快, 最后的结果就变成了保存第一个请求的值
sduoduo233
199 天前
@SingeeKing 我也不懂 java ,但是我觉得如果在 select 和 update 之间 user 的某一项数据更新了,会被 update 覆盖
zhouhu
199 天前
@kanepan19 大佬
pelloz
199 天前
看场景,没要求的位置这么写没问题,写完赶紧下班。有要求的位置简单加一个事务,赶紧下班。对性能有影响了?那就改为乐观锁,改完下班。
crysislinux
199 天前
所以你们的每个表都有类似 version 字段的东西么,实践中很少这样吧,我看到的绝大部分更新都是这样更的。
gadfly3173
199 天前
理论上最好每次只更新自己的字段,但是那样写真的很麻烦吧。要通用的话你就得改造你的 DO ,让他能检测自己被改变了什么字段。
csys
199 天前
真要说起来,这才是“正确”的(或者说是现代的)写法,前提是有乐观锁或者分布式锁

业务系统用数据库事务来做并发控制是个很不好的做法

参考 DDD 中的 repository 和 unit of work 模式

https://martinfowler.com/eaaCatalog/repository.html
https://martinfowler.com/eaaCatalog/unitOfWork.html
9LCRwvU14033RHJo
199 天前
用户资料(姓名、年龄)不就是他自己一个人会更改吗?应该不会有并发问题。
dcsuibian
199 天前
并发你这后端改了也没啥用

实际上最有可能出现的并发问题不在这两行之间。而是前端的问题
比如
1 、甲打开了网页,拿到了 a 和 b 和两个字段,然后就去忙别的去了
2 、乙也打开了网页,拿到了 a 和 b ,然后把 b 修改成 b1 ,接着把 a 和 b1 一起提交上去
3 、甲回来了,把 a 修改成了 a1 ,然后把 a1 和 b 一起提交上去了
4 、最终就输 a1 和 b ,b1 的修改丢失了

正常前端都不会只传变更了的字段,而是偷懒一股脑都传上来
所以你后端其实根本判断不了

不过这其实也没啥大问题,因为通常来说一个表单的正确性就是取决于最后修改他的人而已
既然最后修改他的人觉得没问题,那其实也确实没啥大问题
xuanbg
199 天前
@SingeeKing 会出现你更你的我更我的,大家的原始数据都一样,先更的被后更的还原。
chendy
199 天前
首先,一般没有 CR ,提了测了上了完事
然后,除非并发问题会造成生命财产损失或者大量用户投诉,否则无需在意,更何况是一些并发极少的场景
isnullstring
199 天前
不懂 JAVA
要么先开事务,要么条件里带上原来的值,保证绝对更新
Foxkeh
199 天前
select for update 行锁
Ayanokouji
199 天前
楼主是想问,patch or update 吧,java 一般都是全字段更新(过滤 0 值)。
最好是 new 对象,set 对应值,而不是 select by Id ,然后 set 。
不过,无并发冲突,两种都没问题。
但是如果有并发,两种都有问题,都得加锁。
gbw1992
199 天前
我想了一下,这样的问题除了给数据加上版本号貌似没什么特别好的处理办法了
我觉得还是得看业务,如果这个数据多人共享且并发两很高,那必须加锁
如果没这个需求应该无所谓
GBdG6clg2Jy17ua5
199 天前
严格来说这样是有问题的。
比如你这个场景 1 逻辑是修改了 name,age 。如果另外的场景 2 是修改用户的 phone,并且 phone 修改在前,那么这个 phone 的修改会被场景 1 的旧 phone 覆盖。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1107192

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX