mybatisplus入门教程
文章目录
- mybatisplus入门教程
- 什么是Mybatis Plus
- 快速入门
- 创建数据库 gk_mybatis_plus
- 创建数据库表
- 添加数据
- 创建空的Spring Boot项目
- 添加依赖
- 配置数据库连接MySQL
- 编写代码
- 实体类 GkUserDomain
- mapper
- xml映射文件
- 业务层,实现类
- 控制层
- 创建请求
- 配置日志打印
- 注解
- @TableName
- @TableId
- @TableField
- 自定义`id`生成器
- 分页插件
- 条件构造器
- 批量操作
- 批量录入开始
- 方法一:Mybatis-plus 提供的 saveOrUpdateBatch 11s/1w数据
- 方法二:分组数据再批量添加或修改
- 方法三:mybatis动态SQL`foreach` 3s/w条数据
- 批量录入结束
- 批量查询开始
- 方案一:内置方法selectBatchIds
- 方法二:条件构造器QueryWrapper
- 方案三:编写动态SQL实现
- `sql`耗时
- 添加依赖
- yml配置
- 添加属性文件spy.properties
- 参考博客
mybatisplus官网
Mybatis Plus详细教程
什么是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 提供的 saveOrUpdateBatch 11s/1w数据
controller
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
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;
public static List<GkUserDomain> tempData = new ArrayList(16);
static {
for (int i = 0; i < 10000; i++) {
GkUserDomain user = GkUserDomain.builder().age(i + 10)
.email("abc" + i + "@163.com").name("pmb" + i)
.field1("f" + i)
.field2("f" + i)
.field3("f" + i)
.field4("f" + i)
.field5("f" + i)
.field6("f" + i)
.build();
tempData.add(user);
}
}
/**
* @return
* @description 第一个demo
*/
@GetMapping("test")
public List<GkUserDomain> test() {
List<GkUserDomain> gkUserDomains = gkUserService.listFirst(null);
log.info("abc");
return gkUserDomains;
}
/**
* @param user
* @return
* @description 添加用户
*/
@PostMapping(value = "addUser")
public String addUser(@RequestBody GkUserDomain user) {
gkUserService.save(user);
return "success";
}
/**
* @param list
* @return
* @description 批量添加
*/
@PostMapping(value = "saveBatch")
public String saveBatch() {
long start = System.currentTimeMillis();
gkUserService.saveOrUpdateBatch(tempData);
long end = System.currentTimeMillis();
log.info("批量录入1w耗时:【{}】s", (end - start) / 1000);
return "success";
}
}
业务层service,serviceimpl
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;
}
}
数据层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> {
}
mapper映射文件
<?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="generator.domain.GkUser">
<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"/>
<result property="field1" column="field1" jdbcType="VARCHAR"/>
<result property="field2" column="field2" jdbcType="VARCHAR"/>
<result property="field3" column="field3" jdbcType="VARCHAR"/>
<result property="field4" column="field4" jdbcType="VARCHAR"/>
<result property="field5" column="field5" jdbcType="VARCHAR"/>
<result property="field6" column="field6" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id,name,age,
email,field1,field2,
field3,field4,field5,
field6
</sql>
</mapper>
实体类domain
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.Builder;
import lombok.Data;
/**
* @TableName gk_user
*/
@Data
@TableName("gk_user")
@Builder
public class GkUserDomain {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 邮箱
*/
private String email;
/**
* 备注1
*/
private String field1;
/**
* 备注2
*/
private String field2;
/**
* 备注3
*/
private String field3;
/**
* 备注4
*/
private String field4;
/**
* 备注5
*/
private String field5;
/**
* 备注6
*/
private String field6;
}
效果
POST http://localhost:8080/saveBatch
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 7
Date: Fri, 21 Jul 2023 03:26:03 GMT
Keep-Alive: timeout=60
Connection: keep-alive
success
Response code: 200; Time: 11603ms; Content length: 7 bytes
方法二:分组数据再批量添加或修改
核心思想
先获取数据库表中所有id,从带落库的数据中找到数据库表已经有的id,这样的更新操作;
否则落库。
核心代码
/**
* @param list
* @return
* @description 批量添加2
*/
@PostMapping(value = "saveBatchOptionTwo")
public String saveBatchOptionTwo() {
List<GkUserDomain> result = gkUserService.list();
List<Long> idList = result.stream().map(GkUserDomain::getId).collect(Collectors.toList());
// // 分组
Map<Boolean, List<GkUserDomain>> flagMap = tempData.stream().collect(Collectors.groupingBy(b -> {
return idList.contains(b.getId());
}));
// true:更新 false:修改
gkUserService.updateBatchById(flagMap.get(true));
gkUserService.saveBatch(flagMap.get(false));
return "success";
}
POST http://localhost:8080/saveBatchOptionTwo
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 7
Date: Fri, 21 Jul 2023 04:20:12 GMT
Keep-Alive: timeout=60
Connection: keep-alive
success
Response code: 200; Time: 1268ms; Content length: 7 bytes
方法三:mybatis动态SQLforeach
3s/w条数据
注意:然MyBatis的动态标签的批量操作在数据量特别大的时候,拼接出来的SQL语句过大;
MySQL的服务端对于接收的数据包有大小限制,max_allowed_packet 默认是 4M,需要修改默认配
置或者手动地控制条数,才可以解决这个问题。
3s/1w条数据
优化思路:
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);
}
}
}
}
<insert id="batchSaveMybatis" parameterType="java.util.List">
<foreach collection="list" open="begin" close="end;" separator="," item="data">
insert into gk_user values (
#{data.name,javaType="INTEGER"},
#{data.age,javaType="VARCHAR"},
#{data.email,javaType="VARCHAR"},
#{data.field1,javaType="VARCHAR"},
#{data.field2,javaType="VARCHAR"},
#{data.field3,javaType="VARCHAR"},
#{data.field4,javaType="VARCHAR"},
#{data.field5,javaType="VARCHAR"},
#{data.field6,javaType="VARCHAR"}
)
</foreach>
</insert>
批量录入结束
批量查询开始
方案一:内置方法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 Time:5 ms 2023-07-22 16:20:27
Execute SQL:SELECT 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