mybatisplus入门教程

mybatisplus入门教程

什么是Mybatis Plus

在这里插入图片描述

快速入门

创建数据库 gk_mybatis_plus

在这里插入图片描述

创建数据库表

DROP TABLE IF EXISTS gk_user;
CREATE TABLE gk_user
(
    id    BIGINT(20)  NOT NULL COMMENT '主键ID',
    name  VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age   INT(11)     NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

添加数据


select *
from gk_user;

DELETE
FROM user;INSERT INTO gk_user (id, name, age, email)
VALUES (1, 'Jone', 18, 'test1@baomidou.com'),
       (2, 'Jack', 20, 'test2@baomidou.com'),
       (3, 'Tom', 28, 'test3@baomidou.com'),
       (4, 'Sandy', 21, 'test4@baomidou.com'),
       (5, 'Billie', 24, 'test5@baomidou.com');

创建空的Spring Boot项目

1 创建项目目录
File->New->Project
在这里插入图片描述
2 选择脚手架,jdk版本
在这里插入图片描述
Spring Initializr
Project SDK : java version “1.8.0_131”
choose Initializr Service URL.
Default: https://start.spring.io
3 Spring Boot基本信息
在这里插入图片描述
注意:修改version:2.4.1
在这里插入图片描述
在这里插入图片描述
最终效果空项目
在这里插入图片描述

添加依赖

父工程

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

注意:尽量不要同时导入mybatis和mybatis_plus,版本差异

配置数据库连接MySQL

# DataSource Config
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///mybatis_plus?userUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver

在spring boot启动类中添加@MapperScan注解,扫描Mapper文件夹

package com.geekmice.gkmybatisplusdemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.geekmice.gkmybatisplusdemo.dao")
@SpringBootApplication
public class GkMybatisplusDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(GkMybatisplusDemoApplication.class, args);
    }

}

编写代码

实体类 GkUserDomain
package com.geekmice.gkmybatisplusdemo.domain;

/**
 * @BelongsProject: gk-mybatisplus-demo
 * @BelongsPackage: com.geekmice.gkmybatisplusdemo.domain
 * @Author: pingmingbo
 * @CreateTime: 2023-07-21  09:26
 * @Description: TODO
 * @Version: 1.0
 */

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;


/**
 * @TableName gk_user
 */
@Data
@TableName("gk_user")
public class GkUserDomain {
    /**
     * 主键ID
     */
    private Long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 邮箱
     */
    private String email;

}

注意:@TableName("gk_user") ,这个注解是为了说明映射数据库表,默认gk_user_domain,类似于起别名作用。

mapper
package com.geekmice.gkmybatisplusdemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.geekmice.gkmybatisplusdemo.domain.GkUserDomain;

/**
 * @Entity com.geekmice.gkmybatisplusdemo.domain.GkUser
 */
public interface GkUserMapper extends BaseMapper<GkUserDomain> {


}

xml映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.geekmice.gkmybatisplusdemo.mapper.GkUserMapper">

    <resultMap id="BaseResultMap" type="com.geekmice.gkmybatisplusdemo.domain.GkUserDomain">
            <id property="id" column="id" jdbcType="BIGINT"/>
            <result property="name" column="name" jdbcType="VARCHAR"/>
            <result property="age" column="age" jdbcType="INTEGER"/>
            <result property="email" column="email" jdbcType="VARCHAR"/>
    </resultMap>

    <sql id="Base_Column_List">
        id,name,age,
        email
    </sql>
</mapper>

业务层,实现类
package com.geekmice.gkmybatisplusdemo.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.geekmice.gkmybatisplusdemo.domain.GkUserDomain;

import java.util.List;

/**
 *
 */
public interface GkUserService extends IService<GkUserDomain> {
    List<GkUserDomain> listFirst(Wrapper<GkUserDomain> queryWrapper);
}

package com.geekmice.gkmybatisplusdemo.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geekmice.gkmybatisplusdemo.domain.GkUserDomain;
import com.geekmice.gkmybatisplusdemo.mapper.GkUserMapper;
import com.geekmice.gkmybatisplusdemo.service.GkUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 *
 */
@Service
public class GkUserServiceImpl extends ServiceImpl<GkUserMapper, GkUserDomain>
        implements GkUserService {
    @Autowired
    private GkUserMapper userMapper;

    @Override
    public List<GkUserDomain> listFirst(Wrapper<GkUserDomain> queryWrapper) {
        List<GkUserDomain> result = userMapper.selectList(null);
        return result;
    }
}

控制层
package com.geekmice.gkmybatisplusdemo.controller;

import com.geekmice.gkmybatisplusdemo.domain.GkUserDomain;
import com.geekmice.gkmybatisplusdemo.service.GkUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @BelongsProject: gk-mybatisplus-demo
 * @BelongsPackage: com.geekmice.gkmybatisplusdemo.controller
 * @Author: pingmingbo
 * @CreateTime: 2023-07-21  09:37
 * @Description: TODO
 * @Version: 1.0
 */
@RestController
@Slf4j
public class GkUserController {
    @Autowired
    private GkUserService gkUserService;

    @GetMapping("test")
    public List<GkUserDomain> test() {
        List<GkUserDomain> gkUserDomains = gkUserService.listFirst(null);
        log.info("abc");
        return gkUserDomains;
    }
}
创建请求
GET http://localhost:8080/test
Accept: application/json

###

在这里插入图片描述

配置日志打印

yml

#配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述

注解

@TableName

  • 描述:表名注解,映射实体类对应表
  • 实体类使用

/**
 * @TableName gk_user
 */
@Data
@TableName("gk_user")
public class GkUserDomain {
    /**
     * 主键ID
     */
    private Long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 邮箱
     */
    private String email;

}

@TableId

说明:标识主键,实体类主键字段
没有添加注解@TableId,会生成一个序列号id,自 3.3.0 开始,默认使用雪花算法+UUID(不含中划线)

  {
    "id": 1682215281188872194,
    "name": "zs",
    "age": 10,
    "email": "123@163.com"
  }

添加注解@TableId,没有什么变化,还是生成无序编号id

  {
    "id": 1682215919683575809,
    "name": "ls",
    "age": 11,
    "email": "456@163.com"
  }

type之IdType属性如下
在这里插入图片描述

注意:数据库表主键字段需要设置为自增,整形
在这里插入图片描述

在这里插入图片描述自 3.3.0 开始,默认使用雪花算法+UUID(不含中划线)

@TableField

说明:非主键字段,起别名value=“”

package com.geekmice.gkmybatisplusdemo.domain;

/**
 * @BelongsProject: gk-mybatisplus-demo
 * @BelongsPackage: com.geekmice.gkmybatisplusdemo.domain
 * @Author: pingmingbo
 * @CreateTime: 2023-07-21  09:26
 * @Description: TODO
 * @Version: 1.0
 */

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;


/**
 * @TableName gk_user
 */
@Data
@TableName("gk_user")
public class GkUserDomain {
    /**
     * 主键ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 姓名
     */
	@TableField(value="user_name")
    private String name;



}

自定义id生成器

分页插件

在这里插入代码片

条件构造器

 /**
     * @description 练习mybatis plus 条件构造器
     * @return
     */
    @GetMapping(value = "validQueryWrapper")
    public String validQueryWrapper(){
        QueryWrapper<GkUserDomain> userQueryWrapper = new QueryWrapper<>();
        // 1 查询用户表所有id列信息
        // QueryWrapper<GkUserDomain> tempIdInfos = userQueryWrapper.select("id");
        // java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
        // List<GkUserDomain> domains = gkUserMapper.selectList(tempIdInfos);
        // List<Object> idList = gkUserMapper.selectObjs(userQueryWrapper);

        // 2 查询用户表某几列信息
        // 3 模糊查询
        // userQueryWrapper.likeLeft("name","mb"); // 左模糊
        // log.info("左模糊:[{}]",gkUserMapper.selectList(userQueryWrapper)); // SELECT id FROM gk_user WHERE (name LIKE '%mb')
        // userQueryWrapper.likeRight("name","pmb"); // 右模糊
        // log.info("右模糊:[{}]",gkUserMapper.selectList(userQueryWrapper)); // SELECT id FROM gk_user WHERE (name LIKE '%mb' AND name LIKE 'pmb%')

        // 4 分页查询 todo
        // 使用分页插件

        // 5 全部相等情况
        // HashMap<String, Object> allEqMap = new HashMap<>(16);
        // allEqMap.put("id","1682216842073970971");
        // allEqMap.put("name","pmb0");
        // allEqMap.put("age",10);
        // allEqMap.put("email","abc0@163.com");
        // userQueryWrapper.allEq(allEqMap);
        // log.info("全部相等:[{}]",gkUserMapper.selectList(userQueryWrapper));
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user
        // WHERE (name = 'pmb0' AND id = '1682216842073970971' AND age = 10 AND email = 'abc0@163.com')

        // 6 eq 某个字段相等
        String paramFirst = "abc";
        // // userQueryWrapper.eq("name","pmb1");
        // userQueryWrapper.eq(StringUtils.isNotBlank(paramFirst),"name","pmb2");
        // // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name = 'pmb2')
        // gkUserMapper.selectList(userQueryWrapper);

        //
        // 7 ne 某个字段不相等/外加条件某个字段不相等
        // userQueryWrapper.ne("name","pmb3");
        // userQueryWrapper.ne(StringUtils.contains(paramFirst,"a"),"age","18");
        // gkUserMapper.selectList(userQueryWrapper);
        //SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name <> 'pmb3')
        //SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age <> '18')


        // // 8 排序 asc desc
        // userQueryWrapper.orderByAsc("age");
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user ORDER BY age ASC 升序
        // userQueryWrapper.orderByDesc("age");
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user ORDER BY age DESC 降序
        // gkUserMapper.selectList(userQueryWrapper);

        // // 9 是否为空
        // userQueryWrapper.isNull("name");
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name IS NULL);
        // userQueryWrapper.isNotNull("name");
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name IS NOT NULL)
        // gkUserMapper.selectList(userQueryWrapper);
        //
        // // 10 大于
        // userQueryWrapper.gt("age",19);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age > 19)
        // gkUserMapper.selectList(userQueryWrapper);
        //
        // // 11 大于等于
        // userQueryWrapper.ge("age",20);
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age >= 20)

        //
        // // 12 小于
        // userQueryWrapper.lt("age",11);
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age < 11)

        //
        // // 13 小于等于
        // userQueryWrapper.le("age",22);
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age <= 22)
        //
        // // 14 在a与b之间 between
        // userQueryWrapper.between("age",18,20);
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age BETWEEN 18 AND 20)
        //
        // // 15 不在a,b之间 notBetween
        // userQueryWrapper.notBetween("age",18,20);
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (age NOT BETWEEN 18 AND 20)

        //
        // // 16 在哪几个之内 in
        // userQueryWrapper.in("name","pmb1","pmb2");
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name IN ('pmb1','pmb2'))

        // // 17 不在哪几个之内 notIn
        // userQueryWrapper.notIn("name","pmb1","pmb2","pm3");
        // gkUserMapper.selectList(userQueryWrapper);
        //SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name NOT IN ('pmb1','pmb2','pm3'))
        // // 18 inSql
        // userQueryWrapper.inSql("name","pmb");
        // userQueryWrapper.inSql("name","select name from gk_user where name like '%4'");
        // gkUserMapper.selectList(userQueryWrapper);
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (name IN (select name from gk_user where name like '%4'))

        //
        // // 19 notInSql
        // userQueryWrapper.notInSql("name","pmb1,pmb2,pmb3");
        //
        // // 20 分组 groupBy
        // userQueryWrapper.groupBy("age");
        //
        // // 21 or 或者
        // // 主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)
        userQueryWrapper.inSql("name","select name from gk_user where name like '%4'")
                .or()
                .inSql("name","select name from gk_user where name like '%6'");
        gkUserMapper.selectList(userQueryWrapper);
        //
        // SELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE
        // (name IN (select name from gk_user where name like '%4') OR
        // name IN (select name from gk_user where name like '%6'))

        // return idList.toString();
        return "success";
    }

批量操作

方法一:Mybatis-plus 提供的 saveBatch

数据量10w10w10w10w10w
耗时11s11s11s10s10s

service

public interface UserService extends IService<User> {

}

serviceimpl

public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

}

测试类

package com.geekmice.sbeasypoi.utils;

import com.geekmice.sbeasypoi.SbEasyPoiApplication;
import com.geekmice.sbeasypoi.dao.UserDao;
import com.geekmice.sbeasypoi.entity.User;
import com.geekmice.sbeasypoi.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
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.SpringRunner;

import java.util.ArrayList;
import java.util.Date;

/**
 * @BelongsProject: spring-boot-scaffold
 * @BelongsPackage: com.geekmice.sbeasypoi.utils
 * @Author: pingmingbo
 * @CreateTime: 2023-08-04  13:20
 * @Description: TODO
 * @Version: 1.0
 */
@SpringBootTest(classes = SbEasyPoiApplication.class)
@Slf4j
@RunWith(SpringRunner.class)
public class TestMain {

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserService userService;
    static ArrayList<User> list = new ArrayList<>();
    static {
        for (int i = 0; i < 100000; i++) {
            User build = User.builder().userName(RandomStringUtils.randomAlphabetic(4)).address(RandomStringUtils.random(7))
                    .sex(RandomStringUtils.randomAlphabetic(1)).birthday(new Date()).build();
            list.add(build);
        }
    }


    @Test
    public void t2(){
        long start = System.currentTimeMillis();
        userService.saveBatch(list);
        long end = System.currentTimeMillis();
        long consumeTime = (end - start) / 1000;
        log.info("耗时:【{}】",consumeTime);
    }
}

方法二:Mybatis 动态SQL,在这里插入图片描述

数据量10w10w10w10w10w
耗时17s16s16s16s17s

注意:然MyBatis的动态标签的批量操作在数据量特别大的时候,拼接出来的SQL语句过大;
优化思路:

static int batchSize = 10000;
 
public void createBatch(List<TestPO> entityList) {
    if (!entityList.isEmpty()) {
        int size = entityList.size();
        int idxLimit = Math.min(batchSize, size);
        int i = 1;
        List<TestPO> oneBatchList = new ArrayList<>();
        for (Iterator<TestPO> var7 = entityList.iterator(); var7.hasNext(); ++i) {
            TestPOelement = var7.next();
            oneBatchList.add(element);
            if (i == idxLimit) {
                baseMapper.insertBatchSomeColumn(oneBatchList);
                oneBatchList.clear();
                idxLimit = Math.min(idxLimit + batchSize, size);
            }
        }
    }
}

dao层

public interface UserDao extends BaseMapper<User> {

    void batchSaveMybatis(@Param("list") List<User> list);
}

xml

    <insert id="batchSaveMybatis" parameterType="java.util.List">
        insert into user(user_name,birthday,sex,address) values
        <foreach collection="list"  separator="," item="data">
            (
            #{data.userName},
            #{data.birthday},
            #{data.sex},
            #{data.address}
            )
        </foreach>
    </insert>

测试类

package com.geekmice.sbeasypoi.utils;

import com.geekmice.sbeasypoi.SbEasyPoiApplication;
import com.geekmice.sbeasypoi.dao.UserDao;
import com.geekmice.sbeasypoi.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
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.SpringRunner;

import java.util.ArrayList;
import java.util.Date;

/**
 * @BelongsProject: spring-boot-scaffold
 * @BelongsPackage: com.geekmice.sbeasypoi.utils
 * @Author: pingmingbo
 * @CreateTime: 2023-08-04  13:20
 * @Description: TODO
 * @Version: 1.0
 */
@SpringBootTest(classes = SbEasyPoiApplication.class)
@Slf4j
@RunWith(SpringRunner.class)
public class TestMain {

    @Autowired
    private UserDao userDao;

    @Test
    public void t1(){
        long start = System.currentTimeMillis();
        ArrayList<User> list = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            User build = User.builder().userName(RandomStringUtils.randomAlphabetic(4)).address(RandomStringUtils.random(7))
                    .sex(RandomStringUtils.randomAlphabetic(1)).birthday(new Date()).build();
            list.add(build);
        }
        userDao.batchSaveMybatis(list);
        long end = System.currentTimeMillis();
        int result= (int) ((end-start)/1000);
        log.info("耗时:【{}】",result);
    }
}

在这里插入图片描述

方法三 通过使用InsertBatchSomeColumn方法批量插入

数据量10w10w10w10w10w
耗时15s19s12s13s17s

说明:底层是拼接SQL,但是无需手动编写SQL语句

1 自定义SQL注入器实现DefaultSqlInjector,添加InsertBatchSomeColumn方法

public class EasySqlInjector extends DefaultSqlInjector {
    /**
     * 如果只需增加方法,保留MP自带方法
     * 可以super.getMethodList() 再add
     * @return
     */
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new InsertBatchSomeColumn());
        return methodList;
    }
}

2 添加配置类交给spring容器管理

package com.geekmice.gkmybatisplusdemo.plugin;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @BelongsProject: gk-mybatisplus-demo
 * @BelongsPackage: com.geekmice.gkmybatisplusdemo.plugin
 * @Author: pingmingbo
 * @CreateTime: 2023-07-21  15:57
 * @Description: TODO
 * @Version: 1.0
 */
@Configuration
@MapperScan("com.geekmice.gkmybatisplusdemo.mapper")
public class MybatisPlusConfig {
    @Bean
    public EasySqlInjector easySqlInjector() {
        return new EasySqlInjector();
    }
}

3 编写自定义BaseMapper,加入InsertBatchSomeColumn方法
注意事项:参数只能是list,否则错误找到mappedstatement
参考官网案例说明demo


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

    /**
     * 自定义通用方法
     */
    Integer deleteAll();

    int myInsertAll(T entity);

    /**
     * 如果要自动填充,@{@code Param}(xx) xx参数名必须是 list/collection/array 3个的其中之一
     *
     * @param batchList
     * @return
     */
    int mysqlInsertAllBatch(@Param("list") List<T> batchList);
}
public interface EasyBaseMapper<T> extends BaseMapper<T> {
    /**
     * @description 批量插入
     * @param entityList
     * @return
     */
    int insertBatchSomeColumn(@Param("list") List<T> list);
}

4 将自定义的业务mapper继承自定义的BaseMapper

public interface UserMapper extends EasyBaseMapper<GkUserDomain> {

}

5 测试验证效果

package com.geekmice.gkmybatisplusdemo.plugin;

import com.alibaba.fastjson.JSON;
import com.geekmice.common.annota.MethodExporter;
import com.geekmice.gkmybatisplusdemo.GkMybatisplusDemoApplication;
import com.geekmice.gkmybatisplusdemo.domain.GkUserDomain;
import com.geekmice.gkmybatisplusdemo.mapper.GkUserMapper;
import com.geekmice.gkmybatisplusdemo.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
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.SpringRunner;

import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @BelongsProject: spring-boot-scaffold
 * @BelongsPackage: com.geekmice.gkmybatisplusdemo.plugin
 * @Author: pingmingbo
 * @CreateTime: 2023-07-28  19:14
 * @Description: TODO
 * @Version: 1.0
 */
@SpringBootTest(classes = GkMybatisplusDemoApplication.class)
@Slf4j
@RunWith(SpringRunner.class)
public class ImportAnnotionTest {

    @Autowired
    private UserMapper userMapper;


    @Test
    public void t9() {
        long start = System.currentTimeMillis();
        List<GkUserDomain> gkUserDomains = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 100000; i++) {
            GkUserDomain test = new GkUserDomain();
            test.setUserName(RandomStringUtils.randomAlphabetic(4));
            test.setAge(random.nextInt(20));
            test.setEmail(i + "2" + i + "@163.com");
            test.setField1(RandomStringUtils.randomAlphabetic(8));
            gkUserDomains.add(test);
        }
        userMapper.insertBatchSomeColumn(gkUserDomains);
        long end = System.currentTimeMillis();
        log.info("耗时:【{}】", (end - start) / 1000);
    }
}

方法四:jdbc操作,效率飙升

数据量10w10w10w10w10w
耗时4s6s4s4s5s

核心代码
注意事项
1 yml中rewriteBatchedStatements=true开启
2 事务手动提交关闭。

package com.geekmice.sbeasypoi.utils;

import com.geekmice.sbeasypoi.SbEasyPoiApplication;
import com.geekmice.sbeasypoi.dao.UserDao;
import com.geekmice.sbeasypoi.entity.User;
import com.geekmice.sbeasypoi.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
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.SpringRunner;

import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @BelongsProject: spring-boot-scaffold
 * @BelongsPackage: com.geekmice.sbeasypoi.utils
 * @Author: pingmingbo
 * @CreateTime: 2023-08-04  13:20
 * @Description: TODO
 * @Version: 1.0
 */
@SpringBootTest(classes = SbEasyPoiApplication.class)
@Slf4j
@RunWith(SpringRunner.class)
public class TestMain {

    @Autowired
    private UserDao userDao;
    private String url = "jdbc:mysql://localhost:3306/school?rewriteBatchedStatements=true";
    private String user = "root";
    private String password = "root";
    @Autowired
    private UserService userService;
    static ArrayList<User> list = new ArrayList<>();

    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    static {
        for (int i = 0; i < 100000; i++) {
            User build = User.builder().userName(RandomStringUtils.randomAlphabetic(4)).address(RandomStringUtils.random(7))
                    .sex(RandomStringUtils.randomAlphabetic(1)).birthday(new Date()).build();
            list.add(build);
        }
    }



    @Test
    public void t3(){
        long start = System.currentTimeMillis();
        jdbcSave(list);
        long end = System.currentTimeMillis();
        long consumeTime = (end - start) / 1000;
        log.info("耗时:【{}】",consumeTime);
    }
    private void jdbcSave(List<User> cachedList) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        Connection connection = sqlSession.getConnection();
        PreparedStatement preparedStatement = null;
        sqlSessionFactory.getConfiguration();
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            // connection = DriverManager.getConnection(url, user, password);
            String sql = "insert into user(user_name,birthday,sex,address) values (?,?,?,?)";
            preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            connection.setAutoCommit(false);
            for (User item : cachedList) {
                preparedStatement.setString(1, item.getUserName());
                preparedStatement.setDate(2, new java.sql.Date(item.getBirthday().getTime()));
                preparedStatement.setString(3, item.getSex());
                preparedStatement.setString(4, item.getAddress());
                preparedStatement.addBatch();
            }
            preparedStatement.executeBatch();
            connection.commit();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    log.error("error msg:[{}]", e);
                    throw new RuntimeException(e);
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    log.error("error msg:[{}]", e);
                }
            }
        }
    }
}

批量查询开始

方案一:内置方法selectBatchIds

selectBatchIds根据主键查询
List<Employee> emps=employeeMapper.selectBatchIds(Arrays.asList(1,2,13,14) );

方法二:条件构造器QueryWrapper

List<Long> idList = new ArrayList<>(); // 批量查询的 ID 列表
// 添加要查询的 ID 到 idList 中

QueryWrapper<Entity> queryWrapper = new QueryWrapper<>();
queryWrapper.in("id", idList); // 设置查询条件,in("id", idList) 表示查询 id 字段在 idList 中的记录

List<Entity> entityList = entityMapper.selectList(queryWrapper); // 执行批量查询

方案三:编写动态SQL实现

<select id="studentList" resultType="com.ywt.springboot.model.Student">
        select *
        from student
        where id in
        <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

注:foreach中的 collection标签中为array,item是遍历ids中的每个元素,默认为item可以自定义。

sql耗时

在这里插入图片描述

 Consume Time5 ms 2023-07-22 16:20:27
 Execute SQLSELECT id,name,age,email,field1,field2,field3,field4,field5,field6 FROM gk_user WHERE (id = '1682216842073980917')

添加依赖

        <!--sql耗时-->
        <!-- https://mvnrepository.com/artifact/p6spy/p6spy -->
        <dependency>
            <groupId>p6spy</groupId>
            <artifactId>p6spy</artifactId>
            <version>3.8.6</version>
        </dependency>

yml配置

spring:
  datasource:
    username: root
    password: root
    url: jdbc:p6spy:mysql://localhost:3306/gk_mybatis-plus?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true&serverTimezone=UTC&useSSL=false&allowMultiQueries=true
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver

在这里插入图片描述

添加属性文件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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值