【MyBatis-Plus】实现字段自增的5种实现方式 setSql @TableField @Version
创始人
2024-05-31 06:53:00
0

在使用mybatis-plus的时候,我们需要对某条数据的单一字段进行操作,又不想查出整条数据拿到字段值再加一赋值,此时可以用下面5种方式来实现。

方式一:setSql

官网文档Mybatis-Plus:setSql
官方文档示例:
在这里插入图片描述

i.标准setSql

使用setSql实现字段自增

Wrappers.update(Article).setSql("`read_count` = `read_count` + 1");

缺陷: 如果自增字段名变更时, 需要同步修改setSql的字段字符串.

ii.增强setSql(推荐)

为了解决setSql硬编码问题,联想到参照MyBatis-Plus的设计从lambda方法引用中获取字段对应的数据库字段名, 参照主要源码如下:

  • com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper#columnToString(com.baomidou.mybatisplus.core.toolkit.support.SFunction)
  • com.baomidou.mybatisplus.core.toolkit.LambdaUtils#resolve
  • com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper#getColumn
String column = BlueUtil.columnToUnderline(Article::getReadCount);
Wrappers.lambdaUpdate(Article).setSql(CharSequenceUtil.isNotBlank(column), String.format("`%s` = `%s` + 1", column, column));
  1. 根据lambda方法引用获取属性名
public static  String columnToString(SFunction func) {// 根据lambda方法引用获取SerializedLambdaSerializedLambda lambda = com.baomidou.mybatisplus.core.toolkit.LambdaUtils.resolve(func);// 根据SerializedLambda获取方法名,然后截取出属性名return PropertyNamer.methodToProperty(lambda.getImplMethodName());
}
  1. 根据lambda方法引用获取字段名
public static  String columnToUnderline(SFunction func) {String fieldName = InternalUtil.tryCatch(func, BlueUtil::columnToString);return Optional.ofNullable(fieldName).map(CharSequenceUtil::toUnderlineCase).orElse(CharSequenceUtil.EMPTY);
}
  1. BlueUtil.tryCatch
public static  R tryCatch(T t, Function function) {TimeInterval timer = DateUtil.timer();R r = null;try {r = function.apply(t);} catch (Exception e) {log.error(format("内部方法Function调用异常,错误信息:{}", e.getMessage()), e);}log.info("内部方法Function调用,耗时:{}ms", timer.interval());return r;
}

方式二:MyBatis-Plus update 时 column=column+1(@TableField)

官网问答如何 update 时 column=column+1

i.update 时 column=column+1

使用@TableField实现字段自增

@TableField(update = "%s+1", updateStrategy = FieldStrategy.IGNORED)
private Integer readCount;
baseMapper.update(new Article().setUpdateTime(LocalDateTime.now()),Wrappers.
lambdaUpdate().eq(Article::getId, 123) )

注意: 该方式绑定在entity上,baseMapper提供的 update(entity,updateWrapper) 中的entity不能null,而且所有的update方法均不能再改变此值为字段实际的指定值
缺陷: 该baseMapper所有使用这种方式进行更新表操作时, 都会使readCount字段加一; 如果有些更新操作不希望更新readCount时, 要考虑使用其他方式.

ii.乐观锁

使用@TableField实现字段自增(参考上面),在update时给该字段加where限制条件

baseMapper.update(new Article().setUpdateTime(LocalDateTime.now()),Wrappers.
lambdaUpdate().eq(Article::getReadCount, 0).eq(Article::getId, 123) )

方式三:乐观锁(推荐)

官方文档Mybatis-Plus 乐观锁
Mybatis-Plus基于@Version注解的乐观锁实现

使用@Version实现字段自增

  1. 实例化OptimisticLockerInnerInterceptor,并添加到MyBatis-Plus的拦截器链中;
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;
}
  1. readCount字段加上@Version注解。
@Version
private Integer readCount;

注意:

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下newVersion = oldVersion + 1
  • newVersion会回写到entity
  • 仅支持updateById(id)update(entity, wrapper)方法
  • entity的版本字段必须有值,否则不会生成乐观锁SQL
  • update(entity, wrapper)方法下,wrapper不能复用!!!

MyBatis-Plus开启SQL日志

官网文档启动 mybatis 本身的 log 日志

mybatis-plus.configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

参考文档

Mybatis-Puls条件构造器setSql
Mybatis-Puls如何实现字段自增1
Mybatis-Puls如何 update 时 column=column+1
Mybatis-Plus 乐观锁
Mybatis-Plus 乐观锁
Mybatis-Plus基于@Version注解的乐观锁实现
启动 mybatis 本身的 log 日志

相关内容

热门资讯

自治区财政下达高新技术企业、“... 转自:草原云春潮涌动,助企正当时。申报高新技术企业获得补助,提高了企业应对市场风险、提高发展质量和水...
5.12致敬白衣天使 转自:北京时间 【#5.12致敬白衣天使#】#她是个护士...
5分钟 飙涨近50% 今日早盘,港股三大指数高开高走,恒生科技指数一度涨近3%。截至午间收盘,恒生指数涨0.93%,恒生国...
每周6000+国际航班 外籍游...   民航局消息,今年以来,我国民航国际客运航线网络不断拓展,国际航班量和旅客量进一步增加。  我国通...
​万亿“宁王”,定了! 【导读】宁德时代拟5月20日在港股上市,募资总额将达40亿至50亿美元中国基金报记者 邱德坤5月12...
双向奔“富”:东货西进与西产东... 当西藏牧民巴特尔在海拔4000米的牧场签收到来自山东菏泽的A级芍药时,横亘在西部与东部之间的地理鸿沟...
机构对黄金持续看好,黄金ETF... 截至2025年5月12日 11:30,黄金ETF基金(159937)下跌1.77%,最新报价7.38...
今日75只股长线走稳 站上年线 证券时报·数据宝统计,截至今日上午收盘,上证综指3354.53点,收于年线之上,涨跌幅为0.37%,...
专访丨不确定性加剧背景下巴中深... 新华社巴西利亚5月11日电 专访|不确定性加剧背景下巴中深化合作具有重要意义——访巴西出口投资促进局...
万泽股份跌2.03%,成交额9... 5月12日,万泽股份盘中下跌2.03%,截至13:02,报15.44元/股,成交9444.31万元,...
南方路机涨2.27%,成交额5... 5月12日,南方路机盘中上涨2.27%,截至13:00,报25.63元/股,成交5301.33万元,...
万亿“宁王” 定了! 5月12日,宁德时代披露发行阶段董事会公告及注册招股书,宣布正式启动国际配售簿记,预计5月20日在港...
【西部量化】基金定量研究系列(... (转自:西部证券研究发展中心)本文构建了5个基金特征因子、18个基金净值因子(RBPs),以及11个...
宁德时代动力电池技术获国际航空... 格隆汇5月12日|宁德时代宣布,近日通过AS9100航空航天质量管理体系认证,该认证是由国际航空航天...
融捷股份涨2.01%,成交额7... 5月12日,融捷股份盘中上涨2.01%,截至13:01,报28.87元/股,成交7917.36万元,...
南天信息涨2.08%,成交额2... 5月12日,南天信息盘中上涨2.08%,截至13:01,报19.17元/股,成交2.78亿元,换手率...
粽子里吃出带血创可贴?来伊份:... 5月10日有网友发视频投诉在来伊份买的粽子中吃出疑似带血创可贴“给小孩喂粽子在里面发现了异物(是)创...
让文明成为生活方式,杨浦第二届... 转自:上观新闻日前,上海杨浦第二届文明生活节在长阳创谷举办。市民群众走上城市文明开放麦舞台,观摩文明...
伊外长:可调整铀浓缩水平以与美... 转自:上观新闻据俄罗斯卫星通讯社5月12日报道,伊朗外交部长阿巴斯·阿拉格齐表示,德黑兰不会在铀浓缩...
天蓝水碧迎盛会 转自:廊坊日报 初夏的廊坊绿意盎然。随着2025年廊洽会临近,廊坊精心改善城市环境,提升城市...