mybatisplus入门教程

news2024/11/15 21:29:26

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 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

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

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

相关文章

Vue2基础八、插槽

零、文章目录 Vue2基础八、插槽 1、插槽 &#xff08;1&#xff09;默认插槽 作用&#xff1a;让组件内部的一些 结构 支持 自定义需求: 将需要多次显示的对话框, 封装成一个组件问题&#xff1a;组件的内容部分&#xff0c;不希望写死&#xff0c;希望能使用的时候自定义。…

Redission分布式锁详解

前言 ​ 在分布式系统中&#xff0c;当不同进程或线程一起访问共享资源时&#xff0c;会造成资源争抢&#xff0c;如果不加以控制的话&#xff0c;就会引发程序错乱。而分布式锁它采用了一种互斥机制来防止线程或进程间相互干扰&#xff0c;从而保证了数据的一致性。 常见的分…

【低代码】对低代码未来发展方向的思考

写在前面 看似不起波澜&#xff0c;日复一日的努力&#xff0c;会突然在某一天&#xff0c;让你看到坚持的意义。 1 基础介绍 1.1 什么是低代码 低代码开发是一种软件开发方法&#xff0c;它允许开发人员使用图形界面和少量代码来快速构建应用程序。开发人员可以使用预定义的…

Docker 之 Consul容器服务更新与发现

一、Consul介绍 1、什么是服务注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&#xff0c;也不考虑服务的压力承载&#xff0c;服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构&#xff…

你们公司的【前端项目】是如何做测试的?字节10年测试经验的我这样做的...

前端项目也叫web端项目&#xff08;通俗讲就是网页上的功能&#xff09;是我们能够在屏幕上看到并产生交互的体验。 前端项目如何做测试&#xff1f; 要讲清楚这个问题&#xff0c;先需要你对测试流程现有一个全局的了解&#xff0c;先上一张测试流程图&#xff1a; 测试流程…

QT--day3(定时器事件、对话框)

头文件代码&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> //定时器事件处理时间头文件 #include <QTime> //时间类 #include <QtTextToSpeech> #include <QPushButton> #include <QLabel&g…

AXI协议之AXILite开发设计(二)

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 二、AXI-Lite关键代码分析 1、时钟与…

Bootstrap框架(组件)

目录 前言一&#xff0c;组件1.1&#xff0c;字体图标1.2&#xff0c;下拉菜单组件1.2.1&#xff0c;基本下拉菜单1.2.2&#xff0c;按钮式下拉菜单 1.3&#xff0c;导航组件1.3.1&#xff0c;选项卡导航1.3.2&#xff0c;胶囊式导航1.3.3&#xff0c;自适应导航1.3.4&#xff…

【LeetCode】114.二叉树展开为链表

题目 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例 1&…

【黑马头条之图片识别文字审核敏感词】

本笔记内容为黑马头条项目的图片识别文字审核敏感词部分 目录 一、需求分析 二、图片文字识别 三、Tess4j案例 四、管理敏感词和图片文字识别集成到文章审核 一、需求分析 产品经理召集开会&#xff0c;文章审核功能已经交付了&#xff0c;文章也能正常发布审核。对于上次…

【已解决】React Antd Form.List 表单校验无飘红提示的问题

背景 我想对 Form.List 构建的表单进行校验&#xff0c;比如下拉框中的内容应当至少有一个 XX&#xff0c;表单的长度不能少于多少等等对 List 内容进行校验&#xff0c;并给出飘红提示 问题 比如我有这样一段代码来实现对 list 具体内容的校验&#xff0c;但是写完后发现没有…

专科程序员,想要面试获胜必须要做的两个点

这两天看到一篇关于专科程序员找工作的文章&#xff0c;感受到了其中的坎坷 那么作为专科程序员&#xff0c;我们应该如何获胜&#xff0c;获得工作机会呢&#xff1f; 根据我的经验&#xff0c;以下两点一定会给你带来更多的机会。 一个是学好英语 另外一个是构建自己的…

高层金属做power mesh如何避免via stack

随着工艺精进&#xff0c;pr要处理的层次也越来越多&#xff0c;如何选择power plan的层次尤为关键&#xff0c;一方面决定ir drop的大小&#xff0c;影响着芯片的功能&#xff0c;一方面决定绕线资源&#xff0c;影响面积。 选择高层metal做power mesh的关键在于厚金属&#…

微信小程序开发之配置菜单跳转到自定义页面

需求: 用户点击公众号菜单跳转到自定义带引流码的链接 公众号相关文档: 网页授权 | 微信开放文档 大致流程: 1.在公众号菜单配置链接: https://open.weixin.qq.com/connect/oauth2/authorize?appidXXXXXXXXXXXX&redirect_urihttps%3A%2F%2F测试域名%2Fws_dabai%2Fwe…

i.MX6ULL(二十) linux platform 设备驱动

Linux 系统要考虑到驱动的可重用性&#xff0c;因 此提出了驱动的分离与分层这样的软件思路&#xff0c;在这个思路下诞生了我们将来最常打交道的 platform 设备驱动&#xff0c;也叫做平台设备驱动。 1 Linux 驱动的分离与分层 1.1 驱动的分隔与分离 对于 Linux 这样一…

查看电脑上NET Framework最高版本

1、使用CMD工具 1、进入路径&#xff1a; cd %WINDIR%\Microsoft.NET\Framework\v4.0.303192、查看版本 MSBuild /version2、效果

【Github】自动监测 SSL 证书过期的轻量级监控方案 - Domain Admin

在现代的企业网络中&#xff0c;网站安全和可靠性是至关重要的。一个不注意的SSL证书过期可能导致网站出现问题&#xff0c;给公司业务带来严重的影响。针对这个问题&#xff0c;手动检测每个域名和机器的证书状态需要花费大量的时间和精力。为了解决这个问题&#xff0c;我想向…

NAT详解(网络地址转换)

一句话说清楚它是干什么的&#xff1a; 网络地址转换&#xff1a;是指通过专用网络地址转换为公用地址&#xff0c;从而对外隐藏内部管理的IP地址&#xff0c;它使得整个专用网只需要一个全球IP就可以访问互联网&#xff0c;由于专用网IP地址是可以重用的&#xff0c;所以NAT大…

基于机器学习的供水管网水力模型

大数据、人工智能、物联网等前沿技术正推动人类社会发展发生深刻变革。2021年12月12日&#xff0c;国务院印发了《“十四五”数字经济发展规划》&#xff0c;进一步指明了各行业数字化转型发展的方向。作为传统的民生保障行业&#xff0c;供水行业也面临着向数字化智慧化转型的…

2023年的前端开发还好找工作么

首先可以明确写在前面的是&#xff0c;前端的确是不像之前一样&#xff0c;只会简单的基础就能轻轻松松的找到工作的&#xff0c;随着学习的人不断增多&#xff0c;市场自然会逐步提高对就业人员的要求&#xff0c;那么再以之前的要求来看待前端的话的确是不可取的 互联网在&a…