不能随便的调用mybatisplus的update(对象)会导致全部进行更新,如果调用要小心设置DTO的参数进行避免null更新
前言:今天业务那边发现调用只修改所属项目的单参数接口导致的一条数据里面的其他条数据进行清空了,导致下游获取不到数据,我查了查代码,一眼就发现有问题。问题场景:1、主要是调用了Mybatis的自带的update参数方法,这个是全量的更新类的参数,场景复现:同时写的代码:@Overridepublic void updateByNewsId(TbmNewsProcessing tbmNewsProce
前言:今天业务那边发现调用只修改所属项目的单参数接口导致的一条数据里面的其他条数据进行清空了,导致下游获取不到数据,我查了查代码,一眼就发现有问题。
问题场景:
1、主要是调用了Mybatis的自带的update参数方法,这个是全量的更新类的参数,
场景复现:
同时写的代码:
@Override
public void updateByNewsId(TbmNewsProcessing tbmNewsProcessing) {
LambdaQueryWrapper<TbmNewsProcessing> lambdaQueryWrapper = new LambdaQueryWrapper<TbmNewsProcessing>();
lambdaQueryWrapper.eq(TbmNewsProcessing::getNewsId, tbmNewsProcessing.getNewsId());
processingMapper.update(tbmNewsProcessing, lambdaQueryWrapper);
}
@Override
public void updateAppIds(String newsId, String appIds) {
TbmNewsProcessing tbmNewsProcessing = new TbmNewsProcessing();
tbmNewsProcessing.setUpdateTime(LocalDateTime.now());
tbmNewsProcessing.setNewsId(Long.parseLong(newsId));
tbmNewsProcessing.setAppIds(appIds);
tbmNewsProcessing.setDelReason("接口变更所属项目");
tbmNewsProcessing.setDelType(NewsDeleteTypeEnum.NINE.getType());
updateByNewsId(tbmNewsProcessing);
}
调用的是
com.baomidou.mybatisplus.core.mapper;里面的自带有的方法:
运行的SQL如下
==> Preparing: UPDATE processing SET news_id=?, app_ids=?, trading_market=?, range_base=?, range_plus=?, financial=?, financial_plus=?, form=?, update_time=?, del_type=?, del_reason=?, sentiment=?, news_importance=? WHERE news_id = ?
==> Parameters: 1181793409217(Long), [2, 3, 5, 6, 7](String), null, null, null, null, null, null, 2020-12-08 13:35:07.968(Timestamp), 9(Integer), 接口变更所属项目(String), null, null, 1181793409217(Long)
<== Updates: 1
会把其他参数的null进行更新update,导致的问题会很严重。会把其他参数直接的覆盖掉,导致运行之后其他参数置位空了。这个算是生产事故了!
2、解决办法:
1、update的入参为Object,这个对象的所有参数是数据库里面最新的数据,可以直接调用这个Mapper的update;
比如我使用的方法体是:
tbmNewsProcessingDao.updateByNewsId(tbmNewsProcessing);
@Override
public void updateByNewsId(TbmNewsProcessing tbmNewsProcessing) {
LambdaQueryWrapper<TbmNewsProcessing> lambdaQueryWrapper = new LambdaQueryWrapper<TbmNewsProcessing>();
lambdaQueryWrapper.eq(TbmNewsProcessing::getNewsId, tbmNewsProcessing.getNewsId());
processingMapper.update(tbmNewsProcessing, lambdaQueryWrapper);
}
入参是整体一个对象;
2、单独的写一条update数据进行操作单个字段也是可以的!
/***
* 获取状态和所属项目
* @param newsId
* @return
*/
@Update("update tbm_news_processing t set t.identified=1 where t.news_id=#{newsId}")
int updateIdentified(@Param("newsId") Long newsId);
3、如果全部参数执行那么需要小心设置字段避免被全局更新;实体类的字段不允许有注释:
字段允许为null
(例如时间,有参数要置空允许update,实体类上可以加上这个注解)
@TableField(strategy=FieldStrategy.IGNORED)
不添加这个注解的时候,那么null是不会update的。如果添加了这个注解,那么这个null参数,也会update的。这个特别容易修改。一旦修改会造成很大的麻烦,而且不容易发现!!!!

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)