Mybatis-plus的操作(新增,修改)

Posted 花果水莲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis-plus的操作(新增,修改)相关的知识,希望对你有一定的参考价值。

一、springboot整合mybatis-plus

1.1 springboot在整合mybatis-plus时,pom文件中的坐标

一般同时会引入Druid。

<!-- springboot整合mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>
<!-- springboot整合mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- springboot整合druid-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>

1.2 application.yml配置文件

spring:
  application:
    name: springboot_mysql
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC
      username: root
      password: root

mybatis-plus:
  configuration:
    #执行的sql语句,会打印在控制台上
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      #id增长策略
      id-type: assign_id
      #数据库表与模型的关系
      table-prefix: tbl_

1.3 数据库表与模型关系的映射关系

MP会默认将模型类的类名首字母小写作为表名使用,假如数据库名称都以tbl_开头,那么我们就需要将所有的模型类上添加@TableName,配置起来还是比较繁琐,简化方式可以在配置文件中配置如下内容:

mybatis-plus: 
    global-config: 
        db-config: 
            table-prefix: tbl_

设置前缀的内容,这样MP就会拿tbl_加上模型类的首字母小写,就刚好组装成数据库的表名。

二、新增

2.1、@TableId(type = IdType.策略)注解,主键的生成策略

在向数据库表中新增数据时,往往Id都是自动生成的的,而不是手动维护的。所以可以在实体类中的Id字段上加上注解@TableId(type = IdType.策略),表示字段的生成策略。

2.2、IdType.策略有ASSIGN_ID策略、ASSIGN_UUID策略、INPUT策略、AUTO策略

2.2.1 ASSIGN_ID策略

可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键。所以实体类的字段类型是Long类型的,否则会抛异常。

2.2.2 ASSIGN_UUID策略

可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢。

2.2.3 AUTO策略

数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用

2.2.4 INPUT

不设置id生成策略,MP不自动生成,约等于NONE,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂

2.3、主键生成策略统一配置

如果要在项目中的每一个模型类上都需要使用相同的生成策略,稍微比较繁琐,我们可以在配置文件中添加内容来使用统一的配置:

mybatis-plus: 
    global-config: 
        db-config:
            id-type: assign_id

配置完成之后,每个模型的注解ID策略都将成为assign_id

2.4 新增

Employee employee = new Employee();
employee.setLastName("zhangsan");
employee.setGender(1);
employee.setEmail("zhangsan@qq.com");
employeeMapper.insert(employee);

三、修改

Employee employee = new Employee();
employee.setId(13L);
employee.setLastName("王五");
employee.setEmail("wangwu@qq.com");
employee.setGender(1);
employeeMapper.updateById(employee);

四、自动填充功能

比如创建时间,修改时间等字段,都和当前时间有关系,可以通过set方法设置字段的值。但是也可以通过mybatis-plus提供的自动填充的功能设置字段的值。其步骤如下:

第一步:在实体类需要填充的字段上加注解@TableField(fill=)

@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

第二步:实现mybatis-plus提供的MetaObjectHandler接口

1. 新建handler包,在handler包下创建类MyMetaObjectHandler implements  MetaObjectHandler,并由spring管理,添加@Component注解

2. 类中重载insertFill,updateFill方法。新增的时候会执行insertFill()方法,修改时会执行updateFill()方法。

@Component
public class MyMetaObjectHandler implements MetaObjectHandler 
    @Override
    public void insertFill(MetaObject metaObject) 
        //setFieldValByName:参数1:字段名,参数2:赋值,参数3:metaObject
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    

    @Override
    public void updateFill(MetaObject metaObject) 
        this.setFieldValByName("updateTime",new Date(),metaObject);
    

mybatis-plus的批量新增insertBatchSomeColumn

MyBatis-Plus 是基于 MyBatis 进行封装的一套优秀的持久层框架,它提供了丰富的便捷操作方法和强大的代码生成器,大大简化了 MyBatis 的使用。在 MyBatis-Plus 中,我们可以使用 insertBatchSomeColumn 方法来实现批量新增指定字段的操作。

mybatis-plus的 IService接口 默认提供 saveBatch批量插入,也是唯一一个默认批量插入,在数据量不是很大的情况下可以直接使用,但这种是一条一条执行的效率上会有一定的瓶颈,在这里先看下saveBatch的执行情况

 

 

 

可以看到sql语句是一条一条执行的,插入多少条数据就相当于执行了多少次的插入sql, 点进saveBatch方法,看看内部是怎么实现的

 

 注意看,方法有一个事务注解,说明插入整批数据会作为一个事务进行,

默认1000条一次,怪不得执行时每隔1000条会处于一个准备执行状态,等待几秒后才会往下执行(这里等待的时间就是1000个单条的insert语句执行的时间)

再往下点是一个saveBatch接口,参数分别是插入的对象集合、插入批次数量也就是默认的1000

这里也有一个事务的注解,这是因为saveBatch是一个重载方法,插入的时候也可以指定插入批次数量调用

继续往下进入executeBatch

 

 

这里就是真正执行的方法了,idxLimit会对比DEFAULT_BATCH_SIZE和集合长度两个数中的最小数,作为批量大小,也就是说当集合长度不够1000,那么执行的时候批量大小就是集合的长度,就执行一次。

for循环中的consumer:对应的类型是一个函数式接口,代表一个接受两个输入参数且不返回任何内容的操作符。意思是给定两个参数sqlSession、循环中当前element对象,执行一次传递过来的consumer匿名函数。也就是上边源码里的插入匿名函数。
 

当i == indLimit时:执行一次预插入,并重新计算idxLimit的值

if中idxLimit计算规则:当前idxLimit加batchSize(默认1000) 和 集合长度 取最小值,计算出来的结果肯定不会超过集合的长度,最后的批次时idxLimit等于集合的长度,将这个值作为下一次执行预插入的时间点。

sqlSession.flushStatements():当有处于事务中的时候,起到一种预插入的作用,执行了这行代码之后,要插入的数据会锁定数据库的一行记录,并把数据库默认返回的主键赋值给插入的对象,这样就可以把该对象的主键赋值给其他需要的对象中去了,这里不是事务提交啊。

最后方法执行完后@Transactional注解会默认提交事务,如果调用的方法上还有@Transactional注解,默认的事务传播类型是Propagation.REQUIRED,不会新开启事务,如果没有@Transactional注解才会新开起事务

下面我们使用真正的批量新增方法insertBatchSomeColumn,看看两者的区别

1. 什么是批量新增指定字段

批量新增指定字段是指在一次 SQL 语句中执行多条 INSERT 语句,但是只插入指定的字段。批量新增指定字段可以提高数据操作效率,减少数据库与应用程序之间的网络传输次数,减轻数据库服务器的压力,提高系统的并发性能。

2. MyBatis-Plus 批量新增指定字段的方法的使用

mybatis-plus提供了InsertBatchSomeColumn批量insert方法。通过SQL 自动注入器接口 ISqlInjector注入通用方法 SQL 语句 然后继承 BaseMapper 添加自定义方法,全局配置 sqlInjector 注入 MP 会自动将类所有方法注入到 mybatis 容器中。我们需要通过这种方式注入下。
 

/**
 * 自定义Sql注入
 *
 */

public class EasySqlInjector extends DefaultSqlInjector 
    
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) 
        // 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    

 自定义EasyBaseMapper

/**
 * @author 武天
 * @date 2023/3/22 18:19
 */
public interface EasyBaseMapper<T> extends BaseMapper<T> 
    /**
     * 批量插入 仅适用于mysql
     *
     * @param entityList 实体列表
     * @return 影响行数
     */
    Integer insertBatchSomeColumn(Collection<T> entityList);

 mapper继承的这里改为继承刚书写的自定义mapper

/**
 * 
 * 
 * @author wutian
 * @email $email
 * @date 2022-10-03 22:12:06
 */
@Mapper
public interface BreakDownCluesDao extends EasyBaseMapper<ExcelBreakdownClues> 

调用测试

 

可以看到明显的区别,sql只执行了一条,后面都是入参逗号相隔的形式,耗时也有所优化,这是插入数量不是很多的情况,如果是上万条或者上千万条数据,这种形式的优越性就体现出来了 

3. 批量新增指定字段的注意事项

在使用 MyBatis-Plus 进行批量新增指定字段时,需要注意以下几点:

  • 每次新增的数据量不要过大,建议每批次新增的数据量控制在 1000 条以内。
  • 要新增的指定字段不能为 null,需要手动设置默认值。
  • 如果要新增的指定字段在实体类中有对应的字段值,会被忽略。

以上是关于Mybatis-plus的操作(新增,修改)的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis-Plus:ActiveRecord(根据主键查询新增数据更新操作删除操作根据条件查询)

MyBatis-plus 新增实例,主键ID从很大的数字开始

Mybatis-plus笔记

Mybatis-Plus学习小项目及详细教程

如何解决mybatis-plus调用update方法时,自动填充字段不生效问题

MyBatis-Plus