【MyBatis-Plus】实现字段自增的5种实现方式 setSql @TableField @Version

news2024/11/17 9:48:53

在使用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<T,?>)
  • 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 <T> String columnToString(SFunction<T, ?> func) {
    // 根据lambda方法引用获取SerializedLambda
	SerializedLambda lambda = com.baomidou.mybatisplus.core.toolkit.LambdaUtils.resolve(func);
    // 根据SerializedLambda获取方法名,然后截取出属性名
	return PropertyNamer.methodToProperty(lambda.getImplMethodName());
}
  1. 根据lambda方法引用获取字段名
public static <T> String columnToUnderline(SFunction<T, ?> func) {
    String fieldName = InternalUtil.tryCatch(func, BlueUtil::columnToString);
    return Optional.ofNullable(fieldName).map(CharSequenceUtil::toUnderlineCase).orElse(CharSequenceUtil.EMPTY);
}
  1. BlueUtil.tryCatch
public static <T, R> R tryCatch(T t, Function<T, R> 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.<Article>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.<Article>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 日志

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

好的提高代码质量的方法有哪些?有什么经验和技巧?

用于确保代码质量的6个高层策略&#xff1a; 1 编写易于理解的代码 考虑如下这段文本。我们有意地使其变得难以理解&#xff0c;因此&#xff0c;不要浪费太多时间去解读。粗略地读一遍&#xff0c;尽可能吸收其中的内容。 〓ts〓取一个碗&#xff0c;我们现在称之为A。取一…

《实践论》笔记及当下反思(一)

目录 一句话概括核心观点 笔记 1、人的认识&#xff0c;主要地依赖于物质的生产活动 2、只有人们的社会实践&#xff0c;才是人们对于外界认识的真理性的标准 3、强调理论对于实践的依赖关系&#xff0c;理论的基础是实践&#xff0c;又转过来为实践服务 4、你要知道梨子…

浅析三款大规模分布式文件系统架构设计

什么是文件系统 当提到文件系统&#xff0c;大部分人都很陌生。但我们每个人几乎每天都会使用到文件系统&#xff0c;比如大家打开 Windows、macOS 或者 Linux&#xff0c;不管是用资源管理器还是 Finder&#xff0c;都是在和文件系统打交道。如果大家有自己动手装过操作系统的…

Nacos开机自动启动(不用手动shutdown.cmd)

目录 一.前言 二.利用win服务自动启动nacos 1.1下载WinSW 1.2.准备工作和测试 三.利用脚本启动 21.编写一个bat文件,建议放在nacos的根目录下 四.总结: 一.前言 在实际开发中我们的项目配置nacos时, 每次本机重启电脑和更换网络ip时nacos就会挂机(death), 我们还要手动再去…

什么是B+树

B树是一种树数据结构。B树索引是B树在数据库中的一种实现&#xff0c;是最常见也是数据库中使用最为频繁的一种索引。 先来了解一下什么是索引&#xff1f; 一、索引 数据都是存储在硬盘上的&#xff0c;查询数据不可避免的需要进行IO操作。 索引是一种数据结构&#xff0c…

学习MvvmLight工具

最近学习了一下MvvmLight&#xff0c;觉得有些功能还是挺有特色的&#xff0c;所以记录一下 首先新建也给WPF程序 然后在Nuget里面安装MvvmLightLib 包&#xff0c;安装上面那个也可以&#xff0c;但是安装上面那个会自动在代码里面添加一些MvvmLight的demo &#xff0c;安装M…

零钱兑换II 组合总和 Ⅳ 爬楼梯(0-1背包)

零钱兑换II 但本题和纯完全背包不一样&#xff0c;纯完全背包是凑成背包最大价值是多少&#xff0c;而本题是要求凑成总金额的物品组合个数&#xff01; 回归本题&#xff0c;动规五步曲来分析如下&#xff1a; 确定dp数组以及下标的含义 dp[j]&#xff1a;凑成总金额j的货币组…

【MySQL】P10 事务(1)事务执行,提交与回滚

事务执行&#xff0c;提交与回滚基本概念什么是事务&#xff1f;什么是自动提交&#xff1f;错误事务案例解决方案方式一&#xff1a;控制事务方式二&#xff1a;手动提交与回滚自动提交更改为手动提交进行手动提交错误进行回滚基本概念 什么是事务&#xff1f; 每一个SQL语句…

Unity资源热更新框架

什么是热更新&#xff1f; 游戏上线后&#xff0c;玩家下载第一个版本&#xff08;1G左右或者更大&#xff09;&#xff0c;在之后运营的过程中&#xff0c;如果需要更换UI显示&#xff0c;或者修改游戏的逻辑&#xff0c;这个时候&#xff0c;如果不使用热更新&#xff0c;就需…

VS2008生产动态库、静态库调用案例

静态库创建静态库打开VS2008创建项目如下&#xff1a;选择静态库创建文件// add.h #ifndef _ADD_H_ #define _ADD_H_#include <stdio.h>#ifdef __cplusplus extern "C" { #endif__declspec(dllexport) int myAdd(int a, int b);#ifdef __cplusplus } #endif#e…

Linux:IO库函数

目录标准库IO函数一、fopen二、fwrite三、fread四、fseek五、fclose在编写程序时&#xff0c;离不开IO操作&#xff0c;最常见的IO操作就是用printf函数进行打印&#xff0c;本文主要介绍的是封装后的IO库函数。 标准库IO函数 常使用的IO库函数如下&#xff1a; 函数作用fop…

u盘系统文件删除后的五种恢复方法

U盘是我们日常生活中使用较为普遍的移动存储设备&#xff0c;由于其便携性和易用性广受人们的欢迎。然而&#xff0c;在我们使用U盘的过程中&#xff0c;经常会出现误删文件的情况&#xff0c;例如本来要作为启动盘的u盘&#xff0c;误删里面的系统文件怎么办&#xff1f;当U盘…

MySQL的同步数据Replication功能

MySQL提供了Replication功能&#xff0c;可以实现将一个数据库的数据同步到多台其他数据库。前者通常称之为主库&#xff08;master&#xff09;&#xff0c;后者则被称从库&#xff08;slave&#xff09;。MySQL复制过程采用异步方式&#xff0c;但延时非常小&#xff0c;秒级…

C51---超声波测距

1.主要实现功能&#xff1a;当手靠近传感器时&#xff0c;灯亮&#xff1b;手离开&#xff0c;灯灭 2.器件&#xff1a;51单片机、HC-SR04超声波测距传感器 3.代码&#xff1a; #include "reg52.h" //距离小于10cm&#xff0c;D5亮&#xff0c;D6灭&#xff0c;反之…

Lombok使用@Builder无法build父类属性

文章目录问题描述解决方案使用示例lombok Builder注解和build父类属性问题1、简介2.使用3、Builder注解对类做了什么&#xff1f;问题描述 实体类使用Lombok的Builder来实现Builder模式&#xff0c;但是如果使用了extend继承&#xff0c;则子类无法通过Builder来Build父类属性…

深度学习应用技巧4-模型融合:投票法、加权平均法、集成模型法

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下&#xff0c;深度学习中的模型融合。它是将多个深度学习模型或其预测结果结合起来&#xff0c;以提高模型整体性能的一种技术。 深度学习中的模型融合技术&#xff0c;也叫做集成学习&#xff0c;是指同时使用多个…

CentOS7.5(1804)安装vsftpd(ftp)

1.准备安装包 1. vsftpd-3.0.2-29.el7_9.x86_64.rpm 2. ftp-0.17-67.el7.x86_64.rpm 可以自行下载,也可从我的博客中下载,下载传送门点 这里 2.安装vsftpd #1. 上传文件到服务器上,比如/home目录 #2. 执行以下命令安装 rpm -ivh vsftpd-3.0.2-29.el7_9.x86_64.rpm #3. 启动vsf…

极限的无穷小和无穷大

目录 无穷小&#xff1a; 无穷大&#xff1a; 无穷小&#xff1a; 举几个无穷小量的例子&#xff1a; 以0为极限的意思就是无穷小。 注&#xff1a;无穷小是变量&#xff0c;不能把很小很小的数混为一谈。 2&#xff1a;0是可以作为无穷小的唯一的一个数。 我们进行证明&…

完整教程:使用Spring Boot实现大文件断点续传及文件校验

一、简介 随着互联网的快速发展&#xff0c;大文件的传输成为了互联网应用的重要组成部分。然而&#xff0c;由于网络不稳定等因素的影响&#xff0c;大文件的传输经常会出现中断的情况&#xff0c;这时需要重新传输&#xff0c;导致传输效率低下。 为了解决这个问题&#xff…

【敏捷开发】jenkins「CI持续集成 CD持续部署」

文章目录前言一、安装jenkins1. 部署中的痛点2. 什么是jenkins3. jenkins的安装和配置&#xff08;1&#xff09;下载&#xff08;2&#xff09;安装二、上传到运行服务器1. jenkins构建服务器流程2. 安装jenkins常用插件3. 通过freestyle构建项目4. 将构建服务器上的代码上传到…