疑问: 数据库进行更新时 当数据数据相同时 全字段更新和单字段更新是否有区别

起因是我的代码中更新方法和同事写的不一样
数据层用的mybatis,数据库用的mysql
我的写法

Student s= studentDao.selectById("123");
.......//业务操作
Student sTemp = new Student();
sTemp.setId("123");
sTemp.setSex(0);
studentDao.update(sTemp);

然后我同事是这么写的

Student s= studentDao.selectById("123");
.......//业务操作
s.setId("123");
s.setSex(0);
studentDao.update(s);

那么这里有个问题在mybaits中是判断这个字段有就会加上更新语句
数据库原数据

id   name sex  weight
123  张三   1     120

比如这两段代码执行完成后
我的sql

update Student set sex=0 where id='123';

我同事的sql

update Student set name="张三",sex=0,weight="120" where id='123';

我的做法弊端在于 new了一个对象
我自己的想法是为了节约全字段更新数据的sql执行时间,还有mybatis的的sql拼接

问题1:
数据相同时这两种sql有没有性能差异?我实际测试的时候好像并没有看出有差异,希望有人能告诉我原理

问题2:
以上两种方法到底哪种方法才是正确的

阅读 7.7k
4 个回答

楼上大致正确,但是
1.前者也是通用的,但要多写一些 setXXX 的代码;

2.第二种方式在并发情况下容易导致前面的update失效,除非整个过程加锁:
请求1:
update Student set name="李四";
请求2:
update Student set name="张三",sex=0,weight="120" where id='123';

期望结果:
name="李四",sex=0,weight="120" where id='123'
实际结果:
"张三",sex=0,weight="120" where id='123'

原因:
请求2 setXXX 时,请求1正在执行SQL语句update1,这时候MySQL会加锁。
等到update1执行完后,请求2的SQL语句update2再执行,导致原本update1修改后的
name="李四"又被update2改回了name="张三"。

所以如果要用完整更新,请求2必须在setXXX前加锁,让update1在update2完成后才执行,这样才能避免并发情况下导致前面的update失效的问题。

首先new不new不是关键,当然这个new是没必要的,关键是你的映射文件是如何写的。
建议是需要更新的字段才出现的sql中。

建议你使用mbg, 会自动生成updateByPrimaryKeySelective这种方法,只更新有值的字段。

可以看看这里
后端好书阅读与推荐(续二) - QueenKing - SegmentFault
https://segmentfault.com/a/11...

更新有两种方式,一种是通用性更新:从数据库获得完整对象,然后修改这个对象,然后保存,另一种是针对性更新:直接按条件修改数据库中一些对象的某些字段。前者的好处在于通用,可以将前台传来的表单无论修改了那个字段都可以直接保存,无需更多拼凑,修改任何字段的方法都是相同的,便于统一处理,后者的好处在于性能更好,因为节省了许多不必要字段的传递,而且允许原子性更新,比如inc

写个通用的更新sql,可以用mybatis的条件语句,传值也是传多个值,然后不需要更新的值传null,这样可以避免更新的时候new一个对象,也可以避免没有改动的数据也修改,不过可能字段多了,但是某时只需改一个字段的时候多个参数值为null,不大美观。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏