springboot整合mybatis-plus

  1. 导入依赖
<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

lombok插件可简化javabean书写
2.配置数据库数据源和后面使用到的相关配置

spring.datasource.username=root
spring.datasource.password=18756232770lmh
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#mp中逻辑删除状态默认设置
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
#springboot环境
spring.profiles.active=dev

3.编写实体类

package com.lmh.mpdemp.domain;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

import java.util.Date;
@Data
@TableName("mybatis1")//对应数据表名
public class User {

    //@TableId(type = IdType.ID_WORKER)生成19位值数字类型:Long
    //@TableId(type = IdType.ID_WORKER_STR)生成19位字符类型
    @TableId(type = IdType.ID_WORKER)//主键增长策略
    private Long id;
    private String name;
    private Integer age;
    private String email;

    //自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    //乐观锁
    @Version
    @TableField(fill = FieldFill.INSERT)
    private Integer version;

    //逻辑删除控制字段
    //默认0为可查,1为以被逻辑删除
    @TableLogic
    @TableField(fill = FieldFill.INSERT)//也可以在数据库控制默认值为0
    private Integer deleted;
}

其中@Data是lombok注解简化javabean书写,要使用该方法,需先下载插件,在setting里的plugins里下载,并导入依赖

4.主键增长的使用
@TableId
@TableId(type = IdType.ID_WORKER)生成19位值数字类型:Long
@TableId(type = IdType.ID_WORKER_STR)生成19位字符类型
不写默认为ID_WORKER
还有UUID:生成唯一ID的
AUTO:主键自动增长+1

5.编写Mapper并在主配置类上写上@MapperScan(要扫描的包路径)

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lmh.mpdemp.domain.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper extends BaseMapper<User> {
}

泛型写要mp操作的javabean数据类型,BaseMapper里面封装了很多方法

6.功能拓展(createTime,updateTime)自动填充
编写自动填充处理器handler

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 自动填充类
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    //使用mp实现添加操作,执行该方法
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
        this.setFieldValByName("version",1,metaObject);
        this.setFieldValByName("deleted",0,metaObject);
    }

    //使用mp实现修改操作,执行该方法
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

要使用@Component把处理器加入spring管理

使用步骤:
在需要自动填充的数据上加上@TableField(fill =
FieldFill.INSERT)
其中FieldFill后有很多场景:
INSERT:当mp插入该数据时方法调用
INSERT_UPDATE:当mp插入和修改时该方法执行

7.乐观锁
在数据库表加一个version字段,该字段记录版本,修改一次版本字段增加一次,是的多个同时操作该条记录是只能有一个成功的,其原理是:在修改前,先查询,看版本对不对应,不对应则无法修改成功

步骤:
1.写配置类加入乐观锁插件

@MapperScan("com.lmh.mpdemp.mapper")
@Configuration
public class MyConfig {
    /**
     * 乐观锁插件
     * @return
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }

2.实体类上属性上标记@Version

//乐观锁
    @Version
    @TableField(fill = FieldFill.INSERT)
    private Integer version;

8.分页查询
添加分页插件

/**
     * 分页查询插件
     * @return
     */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }

测试:

//分页查询
    @Test
    public void testFindByPage(){
        //创建page对象
        //传入两个参数,current:当前页 size:每页显示记录数
        Page<User> page=new Page<>(1,1);
        //调用mp分页查询的方法
        //把分页所有数据封装page对象里面
        userMapper.selectPage(page, null);
        System.out.println("total"+page.getTotal());//总记录数
        System.out.println(page.getRecords());//每页数据集合
        System.out.println("pages"+page.getPages());//总页数

        System.out.println(page.hasNext());//是否有下一页
        System.out.println(page.hasPrevious());//是否有上一页
    }

9.逻辑删除
原理:删除的该条数据,在数据库中并没有删除,但查询时是不可查询的,在表中添加一个字段deleted表示状态,默认0为正常,1为已删除,也可以在application.properties里修改

#mp中逻辑删除状态默认设置
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

步骤:1.添加逻辑删除插件

/**
     * 逻辑删除插件
     * @return
     */
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }

2.在实体类对应属性上添加@TableLogic
3.测试

//逻辑删除,意思是查询时不显示结果,但在数据可中有该条数据,依靠一个字段控制状态
    @Test
    public void delete2(){
        userMapper.deleteById(1291035330752847873l);
        //userMapper.selectById(1291035330752847873l);测试结果是Total:0,没有查询到该条数据
        //该条数据的deleted字段变成1了
    }

10.sql执行性能分析
步骤1.在配置类中添加插件

/**
     * SQL执行性能分析
     * 开发测试环境使用,线上不推荐
     * dev:开发环境
     * test:测试环境
     * prod:生产环境
     * @return
     */
    @Bean
    @Profile({"dev","test"})//设置dev test 环境开启
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor=new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(200);//毫秒,超过此处设置得时间这sql不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }

2.application.properties里配置环境

#springboot环境
spring.profiles.active=dev

3.执行sql控制台有如下日志

Time:11 ms - ID:com.lmh.mpdemp.mapper.UserMapper.selectPage
Execute SQL:
    SELECT
        id,
        name,
        age,
        email,
        create_time,
        update_time,
        version,
        deleted 
    FROM
        mybatis1 
    WHERE
        deleted=0 LIMIT 0,1

其中time:11ms,没有超过插件设置的performanceInterceptor.setMaxTime(200);//毫秒,超过此处设置的时间这sql不执行

11.负责的条件查询

@Test
    public void testFind(){
        //创建QueryWrapper对象
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        //通过QueryWrapper设置条件

        //ge,gt,le,lt(>=  >  <=  <)
        wrapper.ge("age",10);

        //eq,ne(==   !=)
        wrapper.eq("name","李四3");

        //between    [val1,val2]
        wrapper.between("age",20,30);

        //like(模糊查询)
        wrapper.like("name","李");

        //orderDesc(排序,降序)/升序orderAsc
        wrapper.orderByDesc("id");//根据id降序排列

        //last
        wrapper.last("limit 1");//向sql语句最后拼接以个语句

        //查询指定列
        wrapper.select("id","name","age");//查询结果只可以看见指定列数据


        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
    }

总体测试

package com.lmh.mpdemp;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lmh.mpdemp.domain.User;
import com.lmh.mpdemp.mapper.UserMapper;
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.Arrays;
import java.util.List;

@SpringBootTest
class MpdempApplicationTests {
@Autowired
private UserMapper userMapper;
    //查询所有
    @Test
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        System.out.println(users);
        //[User(id=1, name=张三, age=12, email=15689hdsj, createTime=Wed Aug 05 22:13:40 CST 2020, updateTime=Wed Aug 05 22:13:47 CST 2020)]
    }

    //插入保存
    @Test
    public void testSave(){
        User user=new User();
        user.setAge(18);
        user.setName("李四5");
        user.setEmail("16656dshgd");
        int insert = userMapper.insert(user);
        System.out.println("insert"+insert);
    }

    //修改操作
    @Test
    public void testUpdate(){
        User user=new User();
        user.setId(1291023312687763457l);
        user.setAge(18);

        int i = userMapper.updateById(user);
        System.out.println("update"+i);
    }

    //乐观锁下的修改操作
    @Test
    public void testUpdate1(){
        //先查询,版本对应才能修改
        User user = userMapper.selectById(1291026957873459201l);
        user.setAge(20);
        userMapper.updateById(user);
        //修改成功,version加1,前提是要在属性上加@Version注解,并配置乐观锁插件
    }

    //多个ID的批量查询
    @Test
    public void testFindByIds(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1291026957873459201l, 1291023312687763457l, 1l));
        for (User user : users) {
            System.out.println(user);
        }
    }

    //分页查询
    @Test
    public void testFindByPage(){
        //创建page对象
        //传入两个参数,current:当前页 size:每页显示记录数
        Page<User> page=new Page<>(1,1);
        //调用mp分页查询的方法
        //把分页所有数据封装page对象里面
        userMapper.selectPage(page, null);
        System.out.println("total"+page.getTotal());//总记录数
        System.out.println(page.getRecords());//每页数据集合
        System.out.println("pages"+page.getPages());//总页数

        System.out.println(page.hasNext());//是否有下一页
        System.out.println(page.hasPrevious());//是否有上一页
    }

    //物理删除
    @Test
    public void delete(){
        userMapper.deleteById(1l);
    }

    //多个ID批量删除
    @Test
    public void delete1(){
        userMapper.deleteBatchIds(Arrays.asList(1291026957873459201l,1291023312687763457l));
    }

    //逻辑删除,意思是查询时不显示结果,但在数据可中有该条数据,依靠一个字段控制状态
    @Test
    public void delete2(){
        userMapper.deleteById(1291035330752847873l);
        //userMapper.selectById(1291035330752847873l);测试结果是Total:0,没有查询到该条数据
        //该条数据的deleted字段变成1了
    }

    //复杂条件查询
    @Test
    public void testFind(){
        //创建QueryWrapper对象
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        //通过QueryWrapper设置条件

        //ge,gt,le,lt(>=  >  <=  <)
        wrapper.ge("age",10);

        //eq,ne(==   !=)
        wrapper.eq("name","李四3");

        //between    [val1,val2]
        wrapper.between("age",20,30);

        //like(模糊查询)
        wrapper.like("name","李");

        //orderDesc(排序,降序)/升序orderAsc
        wrapper.orderByDesc("id");//根据id降序排列

        //last
        wrapper.last("limit 1");//向sql语句最后拼接以个语句

        //查询指定列
        wrapper.select("id","name","age");//查询结果只可以看见指定列数据


        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
    }

}