day01 -- MybatisPlus

1. MybatisPlus简介

有基础的同学可结合资源中的代码一起看
MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生

特性

通用的 CRUD 操作 :内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用 :通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成 :支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式 :支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作 :支持全局通用方法注入( Write once, use anywhere )
内置代码生成器 :采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件 :基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库 :支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件 :可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

2. MybatisPlus快速入门

基于资源中提供的项目,实现下列功能:

新增用户功能

根据id查询用户

根据id批量查询用户

根据id更新用户

根据id删除用户

2.1 MybatisPlus常见注解

@TableName :用来指定表名
@TableId:用来指定表中的主键字段信息

  • IdType枚举
    • AUTO:数据库自增长
    • INPUT:通过set方法自行输入
    • ASSIGN_ID:分配 ID,接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultIdentifierGenerator雪花算法

@TableField:用来指定表中的普通字段信息

  • 常见场景:
    • 成员变量名与数据库字段名不一致
    • 成员变量名以is开头,且是布尔值
    • 成员变量名与数据库关键字冲突
    • 成员变量不是数据库字段

MybatisPlus是如何获取实现CRUD的数据库表信息的?

默认以类名驼峰转下划线作为表名

默认把名为id的字段作为主键

默认把变量名驼峰转下划线作为表的字段名

2.2 MybatisPlus常见配置

java 复制代码
mybatis-plus:
  # 别名扫描包
  type-aliases-package: com.example.mybatisplus.domain.po;
  # Mapper xml 文件位置
  mapper-locations: "classpath*:mapper/**/*.xml"
  configuration:
    # 配置驼峰命名
    map-underscore-to-camel-case: true
    # 配置二级缓存
    cache-enabled: false
  global-config:
    db-config:
      # id用雪花算法生成
      id-type: assign_id
      # 更新策略 : 只更新非空字段
      update-strategy: not_null

2.3 MybatisPlus入门案例

  1. 引入MybatisPlus的起步依赖
bash 复制代码
 <!-- mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.6</version>
        </dependency>
  1. 定义Mapper
    自定义的Mapper继承MybatisPlus提供的BaseMapper接口
bash 复制代码
@Mapper
public interface UserMapper extends BaseMapper<User> {

}
  1. 定义实体类
java 复制代码
@Data
@TableName(value = "tb_user")
public class User {
    /**
     * 用户id
     */
    @TableId(value="id",type = IdType.AUTO)//mp默认采用雪花算法增加
    private Long id;

    /**
     * 用户名
     */
    @TableField("username")
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 注册手机号
     */
    private String phone;

    /**
     * 详细信息
     */
    private String info;

    /**
     * 使用状态(1正常 2冻结)
     */
    private Integer status;

    /**
     * 账户余额
     */
    private Integer balance;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;

    /**
     * 性别(数据中没有的字段)
     */
    @TableField(exist = false)
    private Integer sex;

}
  1. 定义Service接口
bash 复制代码
public interface IUserService extends IService<User> {

}
  1. 定义Service实现
bash 复制代码
@Service
public class IUserServiceImpl extends ServiceImpl<UserMapper,User> implements IUserService {

}
  1. 定义Controller
java 复制代码
@RequestMapping("/users")
@RestController
public class UserController {
	@AutoWired
    private final IUserService userService;
        @PostMapping
    public void saveUser(@RequestBody User user) {
        userService.save(user);
    }
    @GetMapping("{id}")
    public User queryUserById(@PathVariable("id") Long id) {
        return userService.getById(id);
    }
    @GetMapping
    public List<User> queryUserList(@RequestParam("ids") List<Integer> ids) {
        return userService.listByIds(ids);
    }
    @PutMapping
    public void updateUser(@RequestBody User user) {
        userService.updateById(user);
    }
    @DeleteMapping("{id}")
    public boolean deleteUserById(@PathVariable("id") Long id) {
        return userService.removeById(id);
    }
}

3. MybatisPlus核心功能

3.1 条件构造器

  • QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分
  • UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
  • 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码

例:

java 复制代码
    @Test // 查询出名字带o,存款大于1000元的人的id,username,info,balance
    void testQueryWrapper() {
        //1.构建查询条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id","username","info","balance")
                .like("username","o")
                .ge("balance",1000);
        //2.查询,打印
        userMapper.selectList(wrapper).forEach(System.out::println);
    }
    @Test // 查询出名字带o,存款大于1000元的人的id,username,info,balance
    void testLambdaQueryWrapper() {
        //1.构建查询条件
        LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda()
                .select(User::getId,User::getUsername,User::getInfo,User::getBalance)
                .like(User::getUsername,"o")
                .ge(User::getBalance,1000);
        //2.查询,打印
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

    @Test // 更新用户名为Jack的余额为2000
    void testUpdateQueryWrapper() {
        // 1.更新的数据
        User user = new User();
        user.setBalance(2000);
        // 2.更新的条件
        QueryWrapper<User> wrapper  = new QueryWrapper<User>().eq("username","Jack");
        userMapper.update(user,wrapper);
    }
    @Test // 为id为1,2,4的用户余额-200
    void testUpdateListWrapper() {
        // 1.更新的条件
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
                .setSql("balance = balance - 200")
                .in("id",List.of(1L,2L,4L));
        // 2.执行更新
        userMapper.update(null,wrapper);
    }

代码生成器

3.2 自定义SQL

我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分

基于Wrapper构建where条件

java 复制代码
    @Test // 为id为1,2,4的用户余额-200
    void testCustomSQLUpdate() {//自定义sql(结合mp)
        // 1.更新的条件
        List<Long> list = List.of(1L, 2L, 4L);
        int amount = 200;
        // 2。定义条件
        QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id",list);
        // 3.调用自定义方法
        userMapper.updateBalanceByIds(wrapper,amount);
    }

在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew

java 复制代码
@Mapper
public interface UserMapper extends BaseMapper<User> {
    void updateBalanceByIds(@Param("ew") QueryWrapper<User> wrapper, @Param("amount") int amount);
}

自定义SQL,并使用Wrapper条件

java 复制代码
    <update id="updateBalanceByIds">
        UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment}
    </update>

4.扩展功能

4.1 代码生成

mybatis提供插件实现通用代码的自动生成有mybatis X等

如下下面这个插件

先配置数据库(一定要精确到具体的数据库)

再根据具体的数据表生成代码

4.2 静态工具类 -- Db

java 复制代码
    @Override
    public UserVO getUserAndAddressById(Long id) {
        //1.查询用户
        User user = this.getById(id);
        if(user == null || user.getStatus() == UserStatus.FROZEN){
            throw new RuntimeException("用户不存在或状态异常");
        }
        //2.查询用户地址
        List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, user.getId()).list();
        // 3.封装VO
        // 3.1 转UserPO为VO
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        // 3.2 转地址VO
        if(CollUtil.isNotEmpty(addresses)) {
            userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));
        }
        return userVO;
    }

    @Override
    public List<UserVO> getUserAndAddressByIds(List<Long> ids) {
        // 1.查询用户
        List<User> users = listByIds(ids);
        if(CollUtil.isEmpty(users)){//用户不存在,换回空集合
            return Collections.emptyList();
        }
        // 2. 查询用户地址
        // 2.1 获取已查询用户id
        List<Long> collect = users.stream().map(User::getId).collect(Collectors.toList());
        // 2.2 查询用户地址
        List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, collect).list();
        // 2.3 转换成地址VO
        List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
        // 2.4 用户地址集合分组处理,相同用户放入一个集合(组)中
        Map<Long, List<AddressVO>> listMap = new HashMap<>(0);
        if(CollUtil.isNotEmpty(addressVOList)){
            listMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }
        // 3. 封装VO返回
        List<UserVO> userVOS = new ArrayList<>(users.size());
        for (User user : users) {
            // 3.1 转UserPO为VO
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            // 3.2 获取用户地址
            userVO.setAddresses(listMap.get(user.getId()));
            // 3.3 添加到集合中
            userVOS.add(userVO);
        }
        return userVOS;
    }

4.3 逻辑删除

方式一

在原来的常见配置中添加逻辑删除字段

java 复制代码
mybatis-plus:
  # 别名扫描包
  type-aliases-package: com.example.mybatisplus.domain.po;
  # Mapper xml 文件位置
  mapper-locations: "classpath*:mapper/**/*.xml"
  configuration:
    # 配置驼峰命名
    map-underscore-to-camel-case: true
    # 配置二级缓存
    cache-enabled: false
  global-config:
    db-config:
      # id用雪花算法生成
      id-type: assign_id
      # 更新策略 : 只更新非空字段
      update-strategy: not_null
      # 逻辑删除字段
      logic-delete-field: deleted
方式二

在实体类的逻辑删除的字段上添加 @TableLogic注释

java 复制代码
@TableLogic
private Boolean deleted;

任选一种即可

4.4 枚举处理器

  1. 创建枚举类
java 复制代码
package com.example.mybatisplus.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

@Getter
public enum UserStatus {
    NORMAL(1,"正常"),
    FROZEN(2,"冻结"),
    ;
    @EnumValue //对应数据库中的字段类型
    private Integer value;
    @JsonValue //在做json处理时(前端返回时)返回下面属性,不加默认枚举字段(@JsonValue注解desc,那么整个序列化结果就是desc的值)
    private String desc;

    UserStatus(Integer value, String desc) {
        this.value = value;
        this.desc = desc;
    }
}
  1. 配置全局枚举处理器
java 复制代码
mybatis-plus:
  # 别名扫描包
  type-aliases-package: com.example.mybatisplus.domain.po;
  # Mapper xml 文件位置
  mapper-locations: "classpath*:mapper/**/*.xml"
  configuration:
    # 配置驼峰命名
    map-underscore-to-camel-case: true
    # 配置二级缓存
    cache-enabled: false
    # 配置枚举处理器
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.CompositeEnumTypeHandler
  global-config:
    db-config:
      # id用雪花算法生成
      id-type: assign_id
      # 更新策略 : 只更新非空字段
      update-strategy: not_null
      # 逻辑删除字段
      logic-delete-field: deleted
  1. 在实体类中修改成枚举
java 复制代码
    /**
     * 使用状态(1正常 2冻结)
     */
    private UserStatus status;

4.5 JSON处理器

JSON没有统一全局字段,上面的枚举处理器就有全局字段

Java默认使用JacksonTypeHandler

  1. 配置类的属性添加注解
    在实体类上的属性上添加注解,配置开启json处理器自动转换
java 复制代码
    /**
     * 详细信息
     */
    @TableField(value = "info",typeHandler = JacksonTypeHandler.class)//解决指定数据库字段名与实体类属性名不一致问题,开启json处理器自动转换
    private UserInfo info;
  1. 配置类添加注解
java 复制代码
@Data
@TableName(value = "tb_user",autoResultMap = true)//开启自动映射
public class User {
...
}

3.JSON对象的类

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
public class UserInfo {
    private Integer age;
    private String intro;
    private String gender;
}

5.插件

5.1 分页插件

  1. 在配置类中注册MyBatisPlus的核心插件,同时添加分页插件
java 复制代码
package com.example.mybatisplus.config;

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

@Configuration
public class MyBatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 创建MybatisPlusInterceptor对象
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);// 设置数据库类型
        paginationInnerInterceptor.setMaxLimit(1000L);// 设置最大单页限制数量,默认 500 条,-1 不受限制
        interceptor.addInnerInterceptor(paginationInnerInterceptor);// 添加分页插件
        return interceptor;
    }
}
  1. 通过构建page对象去查询
java 复制代码
@Test
    void testPageQuery() {
        //1.准备分页
        // 1.1 分页条件
        int pageNo = 1,pageSize = 2;
        Page<User> page = Page.of(pageNo, pageSize);
        //1.2 排序条件
        page.addOrder(OrderItem.desc("balance"));
        page.addOrder(OrderItem.asc("id"));

        // 2. 分页查询
        Page<User> userPage = iUserService.page(page);
        // 3.解析
        Long total = userPage.getTotal();
        System.out.println("total = " + total);
        long pages = userPage.getPages();
        System.out.println("pages = " + pages);
        List<User> records = userPage.getRecords();
        records.forEach(System.out::println);
    }

业务层实现基本如下:

java 复制代码
    @Override//分页
    public PageDTO<UserVO> queryUserPage(UserQuery userQuery) {
        String name = userQuery.getName();
        Integer status = userQuery.getStatus();
        Integer pageNo = userQuery.getPageNo();
        Integer pageSize = userQuery.getPageSize();
        String sortBy = userQuery.getSortBy();
        Boolean isAsc = userQuery.getIsAsc();
         //1.构建查询条件
        Page<User> page = Page.of(pageNo, pageSize);
        if(StrUtil.isNotBlank(sortBy) && isAsc != null) {
            page.addOrder(new OrderItem().setAsc(isAsc).setColumn(sortBy));
        }else {
            // 默认按照更新时间排序
            page.addOrder(new OrderItem().setAsc(false).setColumn("update_time"));
        }
        // 2.分页查询
        Page<User> userPage = lambdaQuery().like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);
         //3.封装VO
        PageDTO<UserVO> dto = new PageDTO<>();
        dto.setTotal(userPage.getTotal());// 总条数
        dto.setPages(userPage.getPages());// 总页数
        List<User> records = userPage.getRecords();// 当前页数据
        if(CollUtil.isEmpty(records)){
            dto.setList(Collections.emptyList());
            return dto;
        }
        dto.setList(BeanUtil.copyToList(records, UserVO.class));
        // 4.返回
        return dto;
    };

5.2 通用分页实体

上面page显示可以封装,请求对象也可以封装

  1. 在PageDTO中定义方法,将MyBatisPlus中的Page结果转为PageDTO结果
java 复制代码
package com.example.mybatisplus.domain.dto;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "分页结果")
public class PageDTO<V> {
    @ApiModelProperty(value = "总记录数")
    private Long total;
    @ApiModelProperty(value = "总页数")
    private Long pages;
    @ApiModelProperty(value = "数据列表")
    private List<V> list;

    /**
     * 返回空分页结果
     * @param p MybatisPlus的分页结果
     * @param <V> 目标VO类型
     * @param <P> 原始PO类型
     * @return VO的分页对象
     */
    public static <V, P> PageDTO<V> empty(Page<P> p){
        return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());
    }

    /**
     * 将MybatisPlus分页结果转为 VO分页结果
     * @param p MybatisPlus的分页结果
     * @param voClass 目标VO类型的字节码
     * @param <V> 目标VO类型
     * @param <P> 原始PO类型
     * @return VO的分页对象
     */
    public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) {
        // 1.非空校验
        List<P> records = p.getRecords();
        if (records == null || records.size() <= 0) {
            // 无数据,返回空结果
            return empty(p);
        }
        // 2.数据转换
        List<V> vos = BeanUtil.copyToList(records, voClass);
        // 3.封装返回
        return new PageDTO<>(p.getTotal(), p.getPages(), vos);
    }

    /**
     * 将MybatisPlus分页结果转为 VO分页结果,允许用户自定义PO到VO的转换方式
     * @param p MybatisPlus的分页结果
     * @param convertor PO到VO的转换函数
     * @param <V> 目标VO类型
     * @param <P> 原始PO类型
     * @return VO的分页对象
     */
    public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) {
        // 1.非空校验
        List<P> records = p.getRecords();
        if (records == null || records.size() <= 0) {
            // 无数据,返回空结果
            return empty(p);
        }
        // 2.数据转换
        List<V> vos = records.stream().map(convertor).collect(Collectors.toList());
        // 3.封装返回
        return new PageDTO<>(p.getTotal(), p.getPages(), vos);
    }
}
  1. 在PageQuery中定义方法,将PageQuery对象转为MyBatisPlus中的Page对象
java 复制代码
package com.example.mybatisplus.domain.query;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mybatisplus.domain.po.User;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {
    @ApiModelProperty(value = "页码", example = "1")
    private Integer pageNo;
    @ApiModelProperty(value = "每页条数", example = "2")
    private Integer pageSize;
    @ApiModelProperty(value = "排序字段", example = "id")
    private String sortBy;
    @ApiModelProperty(value = "是否升序", example = "true")
    private Boolean isAsc;
    // PageQuery转page
    public <T>  Page<T> toMpPage(OrderItem ... items){
        Page<T> page = Page.of(pageNo, pageSize);
        if(StrUtil.isNotBlank(sortBy) && isAsc != null) {
            page.addOrder(new OrderItem().setAsc(isAsc).setColumn(sortBy));
        }else if(items != null){
            // 默认按照排序
            page.addOrder(items);
        }
        return page;
    }
    // 按照某个条件排序
    public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc){
//        return this.toMpPage(new OrderItem(defaultSortBy, isAsc));
        return this.toMpPage(new OrderItem());
    }
    // 默认排序(按照创建时间降序)
    public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
        return toMpPage("create_time", false);
    }
    // 默认排序(按照更新时间降序)
    public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {
        return toMpPage("update_time", false);
    }
}
java 复制代码
@Data
@EqualsAndHashCode(callSuper = true)
public class UserQuery extends PageQuery{
    @ApiModelProperty("用户名关键字")
    private String name;
    @ApiModelProperty("用户状态:1-正常,2-冻结")
    private Integer status;
    @ApiModelProperty("余额最小值")
    private Integer minBalance;
    @ApiModelProperty("余额最大值")
    private Integer maxBalance;
}

具体分页实现

java 复制代码
    @ApiOperation("根据条件分页查询用户接口")
    @GetMapping("/page")
    public PageDTO<UserVO> queryUserPage(@ApiParam("分页请求参数") UserQuery userQuery) {
        return userService.queryUserPage(userQuery);
    }
java 复制代码
 PageDTO<UserVO> queryUserPage(UserQuery userQuery);
java 复制代码
    @Override//分页
    public PageDTO<UserVO> queryUserPage(UserQuery userQuery) {
        String name = userQuery.getName();
        Integer status = userQuery.getStatus();
        Page<User> page = userQuery.toMpPageDefaultSortByUpdateTimeDesc();
        // 2.分页查询
        Page<User> userPage = lambdaQuery().like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);
         // 3.返回
        return PageDTO.of(userPage, user -> {
            //1.拷贝基础属性
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            //2.处理特殊逻辑(如隐藏名字后两位)
            userVO.setUsername(user.getUsername().substring(0, user.getUsername().length() - 2) + "**");
            return userVO;
        });
    };

注:数据的批量加入需要数据库开启rewriteBatchedStatements=true参数,否则数据条条插入与批量插入差距不大

java 复制代码
    url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true

测试:

条条插入 vs 批量插入

java 复制代码
  private User buildUser(int i) {
        User user = new User();
        user.setUsername("user_"+i);
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
//        user.setInfo("{\"age\": 24, \"intro\": \"国文老师\", \"gender\": \"female\"}");
        user.setInfo(UserInfo.of(24,"国文老师", "female"));
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        return user;
    }
    @Test
    void testInsertOne() {//一条条插入
        long b = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++) {
            iUserService.save(buildUser(i));
        }
        long e = System.currentTimeMillis();
        System.out.println("e - b = " + (e - b));
    }
    @Test
    void testInsertBatch() {
        List<User> list = new ArrayList<>(1000);
        long b = System.currentTimeMillis();
        for(int i = 1; i < 10000; i++) {
            list.add(buildUser(i));
            if(i % 1000 == 0) {
                iUserService.saveBatch(list);
                list.clear();
            }
        }
        long e = System.currentTimeMillis();
        System.out.println("e - b = " + (e - b));

记录:刚学没多久感觉都忘得差不多了
加油!

相关推荐
郑祎亦18 分钟前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis
jokerest12314 小时前
web——sqliabs靶场——第十三关——报错注入+布尔盲注
mybatis
武子康15 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
WindFutrue17 小时前
使用Mybatis向Mysql中的插入Point类型的数据全方位解析
数据库·mysql·mybatis
AiFlutter18 小时前
Java实现简单的搜索引擎
java·搜索引擎·mybatis
天天扭码21 小时前
五天SpringCloud计划——DAY1之mybatis-plus的使用
java·spring cloud·mybatis
武子康2 天前
Java-05 深入浅出 MyBatis - 配置深入 动态 SQL 参数、循环、片段
java·sql·设计模式·架构·mybatis·代理模式
2的n次方_2 天前
MyBatis——#{} 和 ${} 的区别和动态 SQL
数据库·sql·mybatis
jokerest1232 天前
web——sqliabs靶场——第十二关——(基于错误的双引号 POST 型字符型变形的注入)
数据库·sql·mybatis