Mybatis-plus学习笔记1
mybatisplus使用文档见官网https://baomidou.com/introduce/大纲一、快速入门1、添加依赖引入 MyBatis-Plus Starter 依赖SpringBoot2dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.15/version /dependencySpringBoot3dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.15/version /dependencySpringBoot4自3.5.13开始dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot4-starter/artifactId version3.5.15/version /dependency2、配置数据源在application.yml中配置数据源信息# DataSource Config spring: datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.jdbc.Driver username: root password: root123456 url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncodingUTF-8useSSLfalse3、扫描mapper文件夹在 Spring Boot 启动类中添加MapperScan注解扫描 Mapper 文件夹4、实体类package com.doumi.mybatisplus.pojo; import lombok.Data; Data public class User { private Long id; private String name; private Integer age; private Integer sex; private String email; }5、编写mapper接口类package com.doumi.mybatisplus.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.doumi.mybatisplus.pojo.User; public interface UserMapper extends BaseMapperUser { }6、测试类SpringBootTest public class MybatisPlusTest { Autowired private UserMapper userMapper; Test public void testSelectList(){ //通过条件构造器查询一个list集合若没有条件可以设置null为参数 ListUser users userMapper.selectList(null); System.out.println(users); } }二、日志application.yml中添加如下信息# 配置mysql-plus的日志 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl三、自定义功能如同mybatis中一样在UserMapper接口中添加对应的方法名package com.doumi.mybatisplus.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.doumi.mybatisplus.pojo.User; import org.springframework.stereotype.Repository; import java.util.Map; //Repository public interface UserMapper extends BaseMapperUser { /** * 自定义查询信息 */ MapString,Object selectMapById(Integer id); }在UserMapper.xml文件中添加具体的sql定义?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.doumi.mybatisplus.mapper.UserMapper select idselectMapById resultTypemap select * from user where id #{id}; /select /mapper四、service功能IService 是 MyBatis-Plus 提供的一个通用 Service 层接口它封装了常见的 CRUD 操作包括插入、删除、查询和分页等。通过继承 IService 接口可以快速实现对数据库的基本操作同时保持代码的简洁性和可维护性。IService 接口中的方法命名遵循了一定的规范如 get 用于查询单行remove 用于删除list 用于查询集合page 用于分页查询这样可以避免与 Mapper 层的方法混淆。package com.doumi.mybatisplus.service; import com.baomidou.mybatisplus.extension.service.IService; import com.doumi.mybatisplus.pojo.User; /** * mybatis_plus中提供的接口Iservice及实现类serviceImplxxxMapper,xxx */ public interface UserService extends IServiceUser { }package com.doumi.mybatisplus.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.doumi.mybatisplus.mapper.UserMapper; import com.doumi.mybatisplus.pojo.User; import com.doumi.mybatisplus.service.UserService; import org.springframework.stereotype.Service; Service public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { }测试类package com.doumi.mybatisplus; import com.doumi.mybatisplus.pojo.User; import com.doumi.mybatisplus.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.ArrayList; import java.util.List; SpringBootTest public class ServiceTest { Autowired UserService userService; Test public void test() { //查询总记录数 long count userService.count(); System.out.println(count: count); } /** * 批量添加 */ Test public void testInsertBatch() { ListUser users new ArrayList(); for (int i 0; i 10; i) { User user new User(); user.setName(test i); user.setAge(18i); user.setEmail(test i doumi.com); user.setSex(i%20?1:2); users.add(user); } boolean result userService.saveBatch(users); System.out.println(result: result); } }五、常用注解1、TableName设置实体类对应的表名或者通过配置对所有实体设置统一前缀mybatis-plus: # mybatis-plus的全局配置 global-config: db-config: # 设置实体类所对应表的统一前缀 table-prefix: t_2、TableIdmybatis默认把id作为主键并默认采用雪花算法生成id若数据库主键不是id那么需要使用注解声明2.1、单独设置package com.doumi.mybatisplus.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; Data TableName(t_user) public class User { //设置某字段为主键mybatis-plus将按照主键生成策略生成主键值 /** * TableId 的 * value属性用于指定主键的字段 * type 用于设置主键的生成策略默认采用雪花算法生成策略 * */ TableId(value uid,type IdType.AUTO) private Long id; private String name; private Integer age; private Integer sex; private String email; }2.2、 全局设置此外还可以通过全局配置设置统一的主键生成策略TableId的value属性用来指定主键对应的字段TableId的type属性用来指定主键的生成策略常用的主键生成策略2.3 雪花算法3、TableField通过此标签指定属性对应的字段名和TableId的区别是TableId设置主键TableField设置普通字段4、TableLogic1、逻辑删除物理删除真实删除将对应数据从数据库中删除之后查询不到此条被删除的数据逻辑删除假删除将对应数据库中代表是否被删除字段的状态修改为“被删除状态”之后在数据库中仍旧能看到此条数据记录。使用场景可以进行数据恢复2、实现逻辑删除的步骤1、数据库中创建逻辑删除状态列设置默认值为02、实体类中增加逻辑删除字段及对应的注解TableLogic3、测试删除方法删除方法默认增加了逻辑删除字段4、数据库中数据被逻辑删除六、条件构造器和常用接口1、Wrapper介绍2、QueryWrapper2.1 组装查询条件Test public void test01() { /** * 查询用户名包含i年龄在20到30之间,邮箱信息不为null的用户信息 * SELECT uid AS id,user_name AS name,age,sex,email,is_deleted * FROM t_user * WHERE is_deleted0 * AND (user_name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL) */ QueryWrapperUser userQueryWrapper new QueryWrapperUser(); userQueryWrapper.like(user_name, i).between(age, 20, 30).isNotNull(email); ListUser users userMapper.selectList(userQueryWrapper); users.forEach(System.out::println); }2.2 组装排序条件Test public void test02() { /** * 按照年龄降序如果年龄相同则按照id升序 * SELECT uid AS id,user_name AS name,age,sex,email,is_deleted * FROM t_user WHERE is_deleted0 * ORDER BY age DESC,id ASC */ QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.orderByDesc(age).orderByAsc(id); ListUser users userMapper.selectList(userQueryWrapper); users.forEach(System.out::println); }2.3 组装删除条件Test public void test03() { /** * 删除邮箱地址为null的信息 * UPDATE t_user SET is_deleted1 WHERE is_deleted0 AND (email IS NULL) */ QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.isNull(email); int delete userMapper.delete(userQueryWrapper); System.out.println(delete); }2.4 条件的优先级Test public void test04() { /** * 将年龄大于20并且用户名包含a或者邮箱为null的用户信息修改 * UPDATE t_user SET user_name?, age?, email? * WHERE is_deleted0 * AND (age ? AND user_name LIKE ? OR email IS NULL) */ QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.gt(age, 20).like(user_name, a).or().isNull(email); User user new User(); user.setAge(20); user.setEmail(agmail.com); user.setName(小明); int update userMapper.update(user, userQueryWrapper); System.out.println(update); }Test public void test05() { /** * 将用户名中包含a并且年龄大于20或者邮箱为null的用户信息修改 * lambda表达式中的条件优先执行 * * UPDATE t_user SET user_name?, age?, email? * WHERE is_deleted0 * AND (user_name LIKE ? AND (age ? OR email IS NULL)) */ QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.like(user_name, a) .and(i- i.gt(age, 20).or().isNull(email)); User user new User(); user.setAge(20); user.setEmail(agmail.com); user.setName(小明); int update userMapper.update(user, userQueryWrapper); System.out.println(update); }2.5 组装select子句Test public void test06() { /** * 查询用户名年龄、邮箱信息 * 设置查询的字段 * * SELECT user_name,age,email FROM t_user WHERE is_deleted0 */ QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.select( user_name, age,email); userMapper.selectMaps(userQueryWrapper).forEach(System.out::println); }2.6 实现子查询Test public void test07() { /** * 查询id100的用户信息 * * SELECT uid AS id,user_name AS name,age,sex,email,is_deleted * FROM t_user * WHERE is_deleted0 AND (uid IN (select uid from t_user where uid100)) */ QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.inSql(uid,select uid from t_user where uid100); userMapper.selectList(userQueryWrapper).forEach(System.out::println); }3、UpdateWrapperTest public void test08() { /** * 将用户名中包含a并且年龄大于20或者邮箱为null的用户信息修改 * * UPDATE t_user SET user_name?,age? * WHERE is_deleted0 * AND (user_name LIKE ? AND (age ? OR email IS NOT NULL)) */ UpdateWrapperUser userUpdateWrapper new UpdateWrapper(); userUpdateWrapper.like(user_name, a) .and(i - i.gt(age, 20).or().isNotNull(email)); userUpdateWrapper.set(user_name,小白).set(age,20); int update userMapper.update(null,userUpdateWrapper); System.out.println(update); }4、Condition带condition条件的动态条件组装器/** * 条件组装 */ Test public void test09() { String name J; Integer ageBegin 20; Integer ageEnd 30; QueryWrapperUser userQueryWrapper new QueryWrapper(); if(StringUtils.isNotBlank(name)){ userQueryWrapper.like(user_name,name); } if(ageBegin ! null){ userQueryWrapper.gt(age,ageBegin); } if(ageEnd ! null){ userQueryWrapper.lt(age,ageEnd); } userMapper.selectList(userQueryWrapper).forEach(System.out::println); } /** * QueryWrapper提供了带有判断条件的条件组装器 */ Test public void test10() { String name J; Integer ageBegin 20; Integer ageEnd 30; QueryWrapperUser userQueryWrapper new QueryWrapper(); userQueryWrapper.like(StringUtils.isNotBlank(name),user_name,name) .gt(ageBegin!null,age,ageBegin) .lt(ageEnd!null,age,ageEnd); userMapper.selectList(userQueryWrapper).forEach(System.out::println); }5、LambdaQueryWrapper/** * 测试使用LambdaQueryWrapper进行数据查询 * */ Test public void test11() { /** * SELECT uid AS id,user_name AS name,age,sex,email,is_deleted * FROM t_user * WHERE is_deleted0 AND (user_name LIKE ? AND age ?) * */ LambdaQueryWrapperUser lambdaQueryWrapper new LambdaQueryWrapper(); lambdaQueryWrapper.like(User::getName,J); lambdaQueryWrapper.gt(User::getAge,20); userMapper.selectList(lambdaQueryWrapper).forEach(System.out::println); }6、LambdaUpdateWrapper/** * 测试使用LambdaUpdateWrapper 进行数据修改 * UPDATE t_user SET age? WHERE is_deleted0 AND (user_name LIKE ?) */ Test public void test12() { LambdaUpdateWrapperUser updateWrapper new LambdaUpdateWrapper(); updateWrapper.like(User::getName,J); updateWrapper.set(User::getAge,20); int update userMapper.update(null,updateWrapper); System.out.println(update); }七、插件1、分页插件MybatisPlus自带分页插件只需要简单的配置就可以实现分页功能Test public void pageTest02() { /** * SELECT uid AS id,user_name AS name,age,sex,email,is_deleted * FROM t_user WHERE is_deleted0 LIMIT ?,? */ PageUser page new Page(2, 3); IPageUser userIPage userMapper.selectPage(page, null); System.out.println(records:page.getRecords()); System.out.println(page.getPages()); System.out.println(page.getTotal()); System.out.println(page.hasNext()); System.out.println(page.hasPrevious()); }2、乐观锁插件乐观锁实现流程1、数据库增加version字段2、添加乐观锁插件//添加乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());package com.doumi.mybatisplus.config; 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; Configuration //扫描mapper接口的包,可以将次配置放置到MybatisPlusConfig类中 MapperScan(com.doumi.mybatisplus.mapper) public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); //添加分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); //添加乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }3、实体类使用Version增加版本号package com.doumi.mybatisplus.pojo; import com.baomidou.mybatisplus.annotation.Version; import lombok.Data; Data public class Product { private Integer id; private String name; private Integer price; Version//标识乐观锁版本号 private Integer version; }4、增加失败重试package com.doumi.mybatisplus; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.doumi.mybatisplus.mapper.ProductMapper; import com.doumi.mybatisplus.mapper.UserMapper; import com.doumi.mybatisplus.pojo.Product; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; SpringBootTest public class MybatisOptimizeLockTest { Autowired private ProductMapper productMapper; Test public void optimizeLockTest() { /** * 原价100元 * 小李查询并增加50 * 小王查询并减少30 * 老板查询价格 */ Product product productMapper.selectById(1); System.out.println(小李查询结果product); product.setPrice(product.getPrice()50); Product productWang productMapper.selectById(1); System.out.println(小王查询结果productWang); int i productMapper.updateById(product); System.out.println(小李修改结果i); productWang.setPrice(productWang.getPrice()-30); int iWang productMapper.updateById(productWang); System.out.println(小王修改结果iWang); if(iWang0){//操作失败重试 Product productNew productMapper.selectById(1); productNew.setPrice(productNew.getPrice()-30); int iNew productMapper.updateById(productNew); System.out.println(iNew:iNew); } System.out.println(老板查询价格productMapper.selectById(1)); } }八、通用枚举枚举属性使用EnumValue注解指定枚举值在数据库中存储的实际值。支持枚举类中的任意字段如序号或编码。1、全局配置2、枚举定义添加注解EnumValuepackage com.doumi.mybatisplus.enums; import com.baomidou.mybatisplus.annotation.EnumValue; import lombok.Getter; Getter public enum SexEnum { MALE(1,男), FEMALE(2,女); EnumValue//将注解的值存入数据库中 private Integer sex; private String sexName; SexEnum(Integer sex, String sexName) { this.sex sex; this.sexName sexName; } }3、pojo属性中使用enum定义字段4、测试类package com.doumi.mybatisplus; import com.doumi.mybatisplus.enums.SexEnum; import com.doumi.mybatisplus.mapper.UserMapper; import com.doumi.mybatisplus.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; /** * 通用枚举测试类 */ SpringBootTest public class MybatisPlusEnumTest { Autowired private UserMapper userMapper; Test public void test() { User user new User(); user.setAge(18); user.setName(admin); user.setSex(SexEnum.FEMALE); userMapper.insert(user); } }九、代码生成器AutoGenerator 是 MyBatis-Plus 的代码生成器通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码极大的提升了开发效率。1、添加依赖!-- 代码生成器的依赖-- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.15/version /dependency !-- Source: https://mvnrepository.com/artifact/org.freemarker/freemarker -- dependency groupIdorg.freemarker/groupId artifactIdfreemarker/artifactId version2.3.34/version scopecompile/scope /dependency2、使用如下代码进行代码生成package com.doumi.mybatisplus; import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import java.nio.file.Paths; /** * 使用代码生成器根据数据库的表自动自动生成代码 * 包括Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码 * */ public class FastAutoGenerateTest { public static void main(String[] args) { //对应数据库连接信息需要修改 FastAutoGenerator.create(jdbc:mysql://localhost:3306/mybatis_plus?characterEncodingUTF-8useSSLfalse, root, root123456) .globalConfig(builder - builder .author(lyl) .outputDir(/Users/luyulong/liyongli/test/src/main/java)//代码生成路径需要根据需求修改 // .outputDir(Paths.get(System.getProperty(user.dir)) /src/main/java) .commentDate(yyyy-MM-dd) ) .packageConfig(builder - builder .parent(com.doumi.mybatisplus) .entity(entity) .mapper(mapper) .service(service) .serviceImpl(service.impl) .xml(mapper.xml) ) .strategyConfig(builder - builder .entityBuilder() .enableLombok() ) .templateEngine(new FreemarkerTemplateEngine()) .execute(); } }十、多数据源dynamic-datasource是一个开源的 Spring Boot 多数据源启动器提供了丰富的功能包括数据源分组、敏感信息加密、独立初始化表结构等。1、创建数据库及表2、引入依赖3、配置多数据源spring: datasource: dynamic: primary: master strict: false datasource: master: url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver slave_1: url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver slave_2: url: ENC(xxxxx) username: ENC(xxxxx) password: ENC(xxxxx) driver-class-name: com.mysql.jdbc.Driver4、创建用户service在 Service 层的方法或类上使用DS注解即可轻松切换数据源。方法上的注解优先级高于类上的注解。package com.doumi.mybatis_plus_datasource.service.impl; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.doumi.mybatis_plus_datasource.mapper.ProductMapper; import com.doumi.mybatis_plus_datasource.pojo.Product; import com.doumi.mybatis_plus_datasource.service.ProductService; import org.springframework.stereotype.Service; DS(slave) Service public class ProductServiceImpl extends ServiceImplProductMapper, Product implements ProductService { // DS(master) //数据源标签可以写在方法上方法上的优先于类上的 public Product getMyObjectById(Integer id) { return super.getById(id); } }package com.doumi.mybatis_plus_datasource.service.impl; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.doumi.mybatis_plus_datasource.mapper.UserMapper; import com.doumi.mybatis_plus_datasource.pojo.User; import com.doumi.mybatis_plus_datasource.service.UserService; import org.springframework.stereotype.Service; Service DS(master) //不写使用默认数据源 public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { }5、创建测试类package com.doumi.mybatis_plus_datasource; import com.doumi.mybatis_plus_datasource.service.ProductService; import com.doumi.mybatis_plus_datasource.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; SpringBootTest public class TestDataSource { Autowired private UserService userService; Autowired private ProductService productService; Test public void testDataSource() { System.out.println(userService.getById(1)); System.out.println(productService.getMyObjectById(1)); } }十一、MybatisX插件官网地址https://baomidou.com/guides/mybatis-x/1、安装插件2、核心功能1、xml映射跳转MybatisX 提供了便捷的 XML 映射文件与 Java 接口之间的跳转功能让开发者能够快速地在两者之间切换提高开发效率2、代码生成通过 MybatisX您可以轻松地根据数据库表结构生成对应的 Java 实体类、Mapper 接口及 XML 映射文件。如上图会生成对应的pojo、mapper、service等文件3、JPA 风格提示MybatisX 支持 JPA 风格的代码提示包括新增、查询、修改和删除操作的自动代码生成。根据提示写出方法名可以自动生成对应的sql语句生成新增操作生成查询操作生成删除操作