初识MybatisPlus

MybatisPlus的特点

  1. 可以对现有工程只做增强不做改变,引入MybatisPlus后Mybatis的代码依旧可以使用
  2. 方便快捷实现对单表的增删改查
  3. 功能丰富 例如 代码生成,自动分页,自动填充

    使用MybatisPlus

  4. 引入MybatisPlus
    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.7</version>
    </dependency>
  5. 自定义的Mapper 继承MybatisPlus提供的BaseMapper
    注意:BaseMapper需要指定实体类型
    1
    2
    3
    public interface UserMapper extends BaseMapper<User> {

    }

    MybatisPlus的常用注解

  6. @TableName : 用于指定表名
    当实体类名和数据库表名不一致的时候使用
  7. @TableId :用于指定表中的主键字段信息
    可以指定主键的憎长类型,共有三种,(AUTO)数据库自增长,(INPUT)get方式输入,(ASSIGN_ID)自带的雪花算法
    若不指定则默认为yaml配置的方式
  8. @TableFieId :用于指定表中的普通字段信息
    直接上图

MybatisPlus的配置

MybatisPlus的条件构造器

MybatisPlus提供了三种条件构造器

  1. QueryWrapper
    提供了很多关于查询的条件方法,方法很多就不一一展示了,通过一个示例简单说明一下

    将图中sql可简化为
    1
    2
    3
    4
    5
    QueryWrapper queryWrapper = new QueryWrapper<User>()
    .select("id","username","info","balance").like("username","o")
    .gt("blance",1000);

    List<User> list = userMapper.selectList(queryWrapper);
  2. UpdateWrapper
    提供了更新的条件方法
    1
    2
    3
    4
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>()
    .setSql("balance =balance - 200").in("id","1,2,4");

    userMapper.update(null,updateWrapper);

IService接口


MybatisPuls提供了IService接口更帮助我们实现对单表的增删改查
使用IService接口需要两步

  1. 自定义的XXXService接口去继承Iservice接口
  2. XXXService的实现类XXXServiceImpl实现Service的同时也要继承IService的实现类
    注意!! XXXServiceImpl继承IService的实现类的时候需要给IService的实现类两个参数
  3. 第一个参数所对应的Mapper接口,因为在IService的实现类里面是需要引入对应的mapper
    即IService里面很多方法底层还是通过MybatisPuls提供的Mapper的方法实现
  4. 第二个参数为对应的实体对象
    例如
    1
    2
    3
    4
    5
    6
    7
    8
    public interface UserService extends IService<User>{

    }

    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{

    }

    IService的应用

    IService提供更多的方法供我们使用,同样这么多方法也就不一一介绍了
    值得一提的是IService提供的批量插入方法saveBeach方法
    假设我们需要像数据库中插入10000条数据
  5. 单条数据插入
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void test1() {
    long a =System.currentTimeMillis();
    for (int i = 0; i <10000 ; i++) {
    Test1 test =new Test1();
    test.setUser(i);
    test.setName("test"+i);
    tsetService.save(test);
    }
    long b =System.currentTimeMillis();
    System.out.println(b-a);
    }
    最后耗时10180毫秒
  6. 批量插入
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public void test2() {
    long a =System.currentTimeMillis();
    List<Test1> list =new ArrayList<>();
    for (int i = 0; i <10000 ; i++) {
    Test1 test =new Test1();
    test.setUser(i);
    test.setName("test"+i);
    list.add(test);
    if (list.size()==100) {
    tsetService.saveBatch(list);
    }
    }
    long b =System.currentTimeMillis();
    System.out.println(b-a);
    }
    最后耗时264毫秒,显著提升了50倍速度!!!
    当然啦这还不是最快的
  7. MYSQL的rewriteBatchedStatements=true
    在配置数据库的url后面添加rewriteBatchedStatements=true 即可
    代码与上面代码相同不变
    最后耗时202毫秒,由于我直插入了10000条数据所以性能不明显,数据越多明显越大

最后再来说一下rewriteBatchedStatements=true的作用

  1. 如果不加,我们操作会是将一千条数据封装到list中,由list传入数据库,然后每一条数据执行一次insert语句
    所以提升速度的原因是减少了连接数据库的次数
  2. 加上rewriteBatchedStatements=true后,list传入后数据库只需要执行一次insert语句,因为者一千条数据会进行拼接

DB静态工具

介绍之前先看几个需求,前置条件,用户和地址是两个表,用外键链接

根据已经学习到的知识,如果我们想解决第一个问题就需要

  1. 在UserService中不仅仅调用自己的IService提供的方法,也需要调用AddressService
    (当然啦也可以调用AddressMapper)
  2. 解决第三个问题呢就需要在AddressService中调用UserService,这样互相调用的话,业务复杂
    很多个Service层或者Mapper互相调用很大可能会造成循环依赖
    为了解决循环依赖问题,MybatisPlus提供了DB静态工具(注意:需要3.5.0版本以上)
  3. DB提供了和IService几乎一摸一样的方法 不过在调用DB的时候需要将所对应的实体类传入
    利用DB解决问题1

JOSN处理器

作用:如果数据库表中有字段类型为JOSN时,可以使用Mybatis提供的JOSN处理器,简化开发
普通方法我会用一个String类型的变量去接收 表中JOSN类型的字段,但是这样后续业务处理比较麻烦
使用JSON处理器可以解决这个问题,需要三步

  1. 定义一个表中JOSN类型字段锁对应的实体类,用这个实体类类型的变量去接收
  2. 同时需要使用@TableFiled中添加JOSN处理器 即typeHandler=JacksonTypeHandler.class
  3. 在@TableName中加上 autoResultMap =true 返回映射

MybatisPlus的分页功能

MybatisPlus提供了很多拓展功能其中较为常用的就是分页功能

  1. 分页功能的配置类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Configuration
    public class MybatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
    // 1.初始化核心插件
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 2.添加分更插件 和指定数据库类型
    PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(DbType.MysOL)
    pageInterceptor.setMaxLimit(1000L);//设置分页上限
    interceptor.addInnerInterceptor(pagenterceptor);
    return interceptor;
    }
    }

    个人理解:先new一个MybatisPlus的拦截器对象,在new一个分页对象并设置初始值添加到拦截器中

  2. 分页功能的基本使用

    1. 这是简单封装了一个PageVO,用于处理分页查询后的数据,方便返回前端
      1
      2
      3
      4
      5
      pubilc class PageVO<T>{
      public Ingter pages;
      public Ingter total;
      public List<T> list
      }
    2. 简单使用
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      public PageVO<UserVO> queryUsersPage(UserQuery query){
      String name = query.getName();
      Integer status = query.getstatus();
      //1.构建分页条件
      // 1.1.分页条件 Page.of()需要两个参数 一个当前的页数,一个每页查询的数据量
      Page<User>page = Page.of(query.getPageNo(),query.getPagesize());
      // 1.2.排序条件
      page.addorder(new orderItem(query.getSortBy(), query.getIsAsc()));
      //1 2.分页查询
      Page<User> p=lambdaQuery()
      .like( condition: name != null, User::getUsername, name)
      .eq( condition: status != null, User::getstatus, status)
      .page(page);
      // 处理数据
      PageVO(UserVO) pagevo =new PageVO()
      pagevo.setPages(p.getPages);
      pagevo.setTotal(p.getTotal);
      List<User> list = p.getRecords();
      List<UserVO> vo= BeanUtil.copyToList(list,UserVo.class)
      pagevo.setlist(vo);
      return pagevo;
      }
      以上就是一个分页查询用户的简单例子
      在实际功能中 构建分页条件 排序条件 处理数据 这三个步骤在多次分页中代码基本相同
      所以其实可以将这几部分代码抽取成三个工具类,使用到这几个步骤的时候直接调用对应的工具类