MyBatis-Plus进阶和使用实践

MyBatis-Plus进阶和使用实践

一、前言

  1. 环境说明
  • 操作系统:Windows 10 专业版
  • Mybatis-Plus 版本:3.4.2
  • JDK 版本:1.8
  • 开发工具:IntelliJ IDEA 2020.2.2
  1. 简介
  • MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

    特性:

  1. 无侵入、消耗小、强大的 CRUD 操作
  2. 支持 Lambda 形式调用,支持多种数据库
  3. 支持主键自动生成,支持 ActiveRecord 模式
  4. 支持自定义全局通用操作,支持关键词自动转义
  5. 内置代码生成器,内置分页插件,内置性能分析插件
  6. 内置全局拦截插件,内置 SQL 注入剥离器

MyBatis-Plus 官网:https://mp.baomidou.com/

MyBatis-Plus 示例工程:https://gitee.com/baomidou/mybatis-plus-samples/tree/master

MyBatis 官网:https://mybatis.org/mybatis-3/zh/index.html

Maven 仓库:https://mvnrepository.com/

MyBatis-Plus入门和使用实践:https://blog.csdn.net/u011424614/article/details/113791443

二、正文

1.创建项目

1)引入依赖

  • pom.xml 引入依赖 mybatis-plus、lombok、spring-boot
<!-- spring-boot-starter 父工程 -->
<parent>
  <artifactId>spring-boot-starter-parent</artifactId>
  <groupId>org.springframework.boot</groupId>
  <version>2.1.3.RELEASE</version>
</parent>

<dependencies>
  <!-- spring-boot 启动器 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <!-- spring-boot 测试启动器 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <!-- lombok -->
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
  <!-- mybatis-plus spring-boot 启动器 -->
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
  </dependency>
  <!-- mybatis-plus -->
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>3.4.2</version>
  </dependency>
  <!-- mysql 驱动 -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <!-- junit -->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>
</dependencies>

2)SpringBoot配置

  • resources 文件夹创建 application.yml
# mysql 连接配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp-advanced-db?useSSL=false&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: 123456
# 输入日志,查看 sql 语句
logging:
  level:
    root: warn
    org.example.dao: trace
  pattern:
    console: '%p%m%n'
  • App.java 启动 spring-boot
package org.example;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * spring-boot 启动入口
 *
 */
@SpringBootApplication
@MapperScan({"org.example.dao"})
public class App 
{
    public static void main( String[] args )
    {
        SpringApplication.run(App.class, args);
    }
}

3)测试数据

  • sql 脚本
#创建用户表
CREATE TABLE user (
    id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
    name VARCHAR(30) DEFAULT NULL COMMENT '姓名',
    age INT(11) DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
    manager_id BIGINT(20) DEFAULT NULL COMMENT '上级领导id',
    create_time DATETIME DEFAULT NULL COMMENT '创建时间',
	update_time DATETIME DEFAULT NULL COMMENT '修改时间',
	version INT(11) DEFAULT '1' COMMENT '版本',
	deleted INT(1) DEFAULT '0' COMMENT '逻辑删除标识(0.未删除,1.已删除)',
    CONSTRAINT manager_fk FOREIGN KEY (manager_id)
        REFERENCES user (id)
)  ENGINE=INNODB CHARSET=UTF8;

#初始化数据:
INSERT INTO user (id, name, age, email, manager_id
	, create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL
		, '2019-01-11 14:20:20'),
	(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553
		, '2019-02-05 11:12:22'),
	(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385
		, '2019-02-14 08:31:16'),
	(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385
		, '2019-01-14 09:15:15'),
	(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385
		, '2019-01-14 09:48:16');
  • 创建 entity/User.java
package org.example.entity;

import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;

import java.time.LocalDateTime;

/***
 * 用户实体类
 * */
@Data
public class User extends Model {
    // 用户 ID
    private Long id;
    // 姓名
    private String name;
    // 年龄
    private Integer age;
    // 邮箱
    private String email;
    // 上级领导 ID
    private Long managerId;
    // 创建时间
    private LocalDateTime createTime;
    // 更新时间
    private LocalDateTime updateTime;
    // 版本
    private Integer version;
    // 逻辑删除标识(0.未删除,1.已删除)
    private Integer deleted;
}
  • 创建 dao/UserMapper.java (接口)
package org.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.example.entity.User;

public interface UserMapper extends BaseMapper<User> {

}

4)测试例子

  • 测试类:AppTest.java
package org.example;

import org.example.dao.UserMapper;
import org.example.entity.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class AppTest 
{
    @Autowired
    private UserMapper userMapper;

    /**
     * 查询列表
     * */
    @Test
    public void select()
    {
        List<User> users = userMapper.selectList(null);
        // 判断预期值与实际值是否相同
        // Assert.assertEquals(5, users.size());
        // 循环输出
        users.forEach(System.err::println);
    }
}

2.逻辑删除

逻辑删除-MP官网:https://mp.baomidou.com/guide/logic-delete.html

使用场景: 1.保留业务数据; 2.主外键关联,不方便删除

  • application.yml 配置逻辑删除默认值
# mybatis-plus
mybatis-plus:
  # 全局主键配置
  global-config:
    db-config:
      # 逻辑删除:标记为正常的值
      logic-not-delete-value: 0
      # 逻辑删除:标记为删除的值
      logic-delete-value: 1
  • entity/User.java

@TableLogic :标记逻辑删除属性

@TableField(select = false) :查询时排除掉当前属性

public class User {
    
    ......
        
    // 逻辑删除标识(0.未删除,1.已删除)
    @TableLogic
    @TableField(select = false)
    private Integer deleted;
}
  • 测试类:AppTest.java
@Test
public void deleteById()
{
    Long userid = 1088250446457389058L;
    // 根据 ID 删除数据
    Integer num = userMapper.deleteById(userid);
    System.out.println("受影响行数:"+num);
    // 查询删除结果
    List<User> users = userMapper.selectList(null);
    users.forEach(System.err::println);
}

结果:

1.删除方法,最终执行的是 update 语句

2.查询方法,最终执行的查询 SQL 中添加了逻辑删除的属性,只查询未删除的数据

注意事项:

  1. 执行修改时,会自动添加逻辑删除属性,作为其中的一个条件
  2. 自定义 SQL 不会自动添加逻辑删除属性(解决:1.删除标识加到 Wrapper 中;2.删除标识加到 SQL 中)

3.自动填充

自动填充-MP官网:https://mp.baomidou.com/guide/auto-fill-metainfo.html

使用场景: 自动填充创建时间和修改时间

  • entity/User.java

@TableField(fill = FieldFill.INSERT) :执行新增操作时,进行填充

@TableField(fill = FieldFill.UPDATE) :执行修改操作时,进行填充

public class User {

    ......
    
    // 创建时间
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    // 更新时间
    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;
}
  • 创建 componect/MyMetaObjectHandler.java

实现:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler 接口

package org.example.componect;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        // 当属性存在时,在执行自动填充操作
        boolean hasSetter = metaObject.hasSetter("createTime");
        // 当属性未设置值时,在执行自动填充操作
        Object val = getFieldValByName("createTime", metaObject);
        if(hasSetter && val == null){ // 属性存在,且未设置值
            setFieldValByName("createTime", LocalDateTime.now(), metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 当属性存在时,在执行自动填充操作
        boolean hasSetter = metaObject.hasSetter("updateTime");
        // 当属性未设置值时,在执行自动填充操作
        Object val = getFieldValByName("updateTime", metaObject);
        if(hasSetter && val == null){ // 属性存在,且未设置值
            setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }
}
  • 测试类:AppTest.java
@Test
public void insert()
{
    User user = new User();
    user.setName("李小龙");
    user.setAge(22);
    user.setEmail("lxl@163.com");
    user.setManagerId(1088248166370832385L);
    // 插入数据
    int num = userMapper.insert(user);
    System.err.println("影响记录数据:"+num);
    System.err.println("主键:"+user.getId());
}

@Test
public void updateById()
{
    User user = new User();
    user.setId(1360237954211033089L);
    user.setAge(23);
    // 更新数据
    int num = userMapper.updateById(user);
    System.err.println("影响记录数据:"+num);
}

4.乐观锁

乐观锁-维基百科:https://zh.wikipedia.org/wiki/%E4%B9%90%E8%A7%82%E5%B9%B6%E5%8F%91%E6%8E%A7%E5%88%B6

乐观锁-MP官网:https://mp.baomidou.com/guide/interceptor-optimistic-locker.html#optimisticlockerinnerinterceptor

使用场景: 防止更新冲突

  • config/MybatisPlusConfig.java
package org.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁插件
        return interceptor;
    }
}
  • entity/User.java
public class User {
    
    ......
    
    // 版本
    @Version
    private Integer version;
}
  • 测试类:AppTest.java
@Test
public void updateById()
{
    // 查询数据,获取当前版本
    Long userid = 1360237954211033089L;
    User user = userMapper.selectById(userid);

    // 更新数据
    user.setAge(23);
    int num = userMapper.updateById(user);
    System.err.println("影响记录数据:"+num);
}

5.性能分析

执行 SQL 分析-MP官网:https://mp.baomidou.com/guide/p6spy.html

p6spy-GitHub:https://github.com/p6spy/p6spy

使用场景: 输出每条 SQL 语句执行时间

注意: 该插件有性能损耗,不建议生产环境使用。

建议: 开发环境和测试环境配置 p6spy 驱动;生产环境配置正常的数据库连接驱动

  • pom.xml
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.9.1</version>
</dependency>
  • resources/application.yml

数据源配置修改:driver-class-name 和 url

spring:
  datasource:
    # driver-class-name: com.mysql.cj.jdbc.Driver
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    # url: jdbc:mysql://localhost:3306 ......
    url: jdbc:p6spy:mysql://localhost:3306 ......
    ......
  • 创建 resources/spy.properties
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
# 输出到日志文件
# logfile=spylog.log
  • 测试类:AppTest.java
@Test
public void select()
{
    List<User> users = userMapper.selectList(null);
    // 循环输出
    users.forEach(System.err::println);
}

6.多租户

多租户技术-维基百科:https://zh.wikipedia.org/wiki/%E5%A4%9A%E7%A7%9F%E6%88%B6%E6%8A%80%E8%A1%93

多租户-MP官网:https://mp.baomidou.com/guide/interceptor-tenant-line.html#tenantlineinnerinterceptor

使用场景: 多用户的环境下共享相同的数据库,例如:当前用户只能查询自己创建的数据

  • config/MybatisPlusConfig.java
package org.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Arrays;
import java.util.List;

@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 多租户 sql 解析器
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public String getTenantIdColumn() {
                return "manager_id"; // 实现多租户的数据库表字段名
            }

            @Override
            public Expression getTenantId() {
                // 一般从 session 或 配置文件中获取
                Long managerId = 1088248166370832385L;
                return new LongValue(managerId); // 传入的多租户值
            }

            @Override
            public boolean ignoreTable(String tableName) {
                List<String> list = Arrays.asList("rols", "power");
                return list.contains(tableName);
                // return false;// 表示当前表需要添加多租户过滤;如果不需要,判断表名后,返回 true 即可
            }
        }));

        // 分页插件
        // 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
        // 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = false
        // PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // interceptor.addInnerInterceptor(paginationInnerInterceptor);

        return interceptor;
    }
}
  • 测试类:AppTest.java

实际情况:CURD 都会生效

方法级取消多租户信息:Mapper 方法上添加注解 @InterceptorIgnore(tenantLine = "true")

@Test
public void select()
{
    List<User> users = userMapper.selectList(null);
    // 循环输出
    users.forEach(System.err::println);
}

7.动态表

动态表-MP官网:https://mp.baomidou.com/guide/interceptor-dynamic-table-name.html

  • 使用场景: 不同的表,表结构相同(数据量大);例如:日志表,根据月份进行拆分

  • config/MybatisPlusConfig.java

package org.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.HashMap;
import java.util.Random;

@Configuration
@EnableTransactionManagement
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 动态表(这里需要先创建 user_2018 和 user_2019 两张表)
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor 
            = new DynamicTableNameInnerInterceptor();
        HashMap<String, TableNameHandler> map = new HashMap<String, TableNameHandler>(2) {{
            put("user", (sql, tableName) -> {
                String year = "_2018";
                int random = new Random().nextInt(10);
                if (random % 2 == 1) {
                    year = "_2019";
                }
                return tableName + year;
            });
        }};
        dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }
}
  • 测试类:AppTest.java

方法级取消动态表名替换:Mapper 方法上添加注解 @InterceptorIgnore(dynamicTableName= "true")

@Test
public void select()
{
    List<User> users = userMapper.selectList(null);
    // 循环输出
    users.forEach(System.err::println);
}

8.SQL注入器

SQL 注入器-MP官网:https://mp.baomidou.com/guide/sql-injector.html

1)自定义

  • 使用场景: 自定义通用方法;例如:BaseMapper 的方法

    步骤:

  1. 创建自定义方法的类
  2. 创建注入器
  3. 将自定义方法添加到 Mapper 中
  • 创建 method/DeleteAllMethod.java

继承 com.baomidou.mybatisplus.core.injector.AbstractMethod

package org.example.method;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

public class DeleteAllMethod extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        // 定义 sql 语句
        String sql = "delete from " + tableInfo.getTableName();
        // 定义方法名
        String method = "deleteAll";
        // sql 源
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        // delete 方法
        return addDeleteMappedStatement(mapperClass, method, sqlSource);
    }
}
  • 创建 injector/MySqlInjector.java
package org.example.injector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import org.example.method.DeleteAllMethod;

import java.util.List;

@Component
public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methods = super.getMethodList(mapperClass); // 获取之前已添加的方法类
        methods.add(new DeleteAllMethod()); // 添加自定义的方法类
        return methods;
    }
}
  • 创建 dao/MyMapper.java

继承 com.baomidou.mybatisplus.core.mapper.BaseMapper

package org.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface MyMapper<T> extends BaseMapper<T> {

    /**
     * 删除所有数据
     * @return 受影响行数
     * */
    public int deleteAll();
}
  • dao/UserMapper.java

继承 MyMapper

package org.example.dao;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.example.entity.User;

import java.util.List;

public interface UserMapper extends MyMapper<User> {

    ......
}
  • 测试类:AppTest.java

方法级取消动态表名替换:Mapper 方法上添加注解 @InterceptorIgnore(dynamicTableName= "true")

@Test
public void deleteAll()
{
    Integer num = userMapper.deleteAll();
    System.out.println("受影响行数:"+num);
}

2)MP选装件

选装件-MP官网:https://baomidou.com/guide/crud-interface.html#mapper-%E5%B1%82-%E9%80%89%E8%A3%85%E4%BB%B6

  • MP 写好的方法,但是并没有添加到 BaseMapper 中;需要手动在 injector/MySqlInjector.java 中添加

选装件目录:com.baomidou.mybatisplus.extension.injector.methods

类名说明
InsertBatchSomeColumn批量插入,可排除某些字段
LogicDeleteByIdWithFill根据 id 逻辑删除数据,并带字段填充功能;例如:逻辑删除时,修改操作人字段
AlwaysUpdateSomeColumnById根据 id 更新固定的某些字段

InsertBatchSomeColumn 为例:

  • injector/MySqlInjector.java
package org.example.injector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import org.example.method.DeleteAllMethod;

import java.util.List;

@Component
public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methods = super.getMethodList(mapperClass); // 获取之前已添加的方法类
        methods.add(new DeleteAllMethod()); // 添加自定义的方法类
        methods.add(new InsertBatchSomeColumn(t->!t.isLogicDelete())); // 不是逻辑删除的字段都包含在内
        return methods;
    }
}
  • dao/MyMapper.java

继承 com.baomidou.mybatisplus.core.mapper.BaseMapper

package org.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import java.util.List;

public interface MyMapper<T> extends BaseMapper<T> {

    /**
     * 删除所有数据
     * @return 受影响行数
     * */
    public int deleteAll();

    /**
     * 批量插入
     * @return 受影响行数
     * */
    public int insertBatchSomeColumn(List<T> list);
}
  • dao/UserMapper.java

继承 MyMapper

  • 测试类:AppTest.java

方法级取消动态表名替换:Mapper 方法上添加注解 @InterceptorIgnore(dynamicTableName= "true")

@Test
public void insertBatchSomeColumn()
{
    User user = new User();
    user.setName("李小龙");
    user.setAge(22);
    user.setEmail("lxl@163.com");
    user.setManagerId(1088248166370832385L);

    User user2 = new User();
    user2.setName("李二龙");
    user2.setAge(25);
    user2.setEmail("lel@163.com");
    user2.setManagerId(1088248166370832385L);

    List<User> users = Arrays.asList(user, user2);
    // 插入数据
    int num = userMapper.insertBatchSomeColumn(users);
    System.err.println("影响记录数据:"+num);
    System.err.println("主键:"+user.getId());
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趴着喝可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值