美文网首页
Mybatis-Plus使用与配置

Mybatis-Plus使用与配置

作者: 攻城老狮 | 来源:发表于2020-08-25 14:15 被阅读0次

    本测试项目涵盖了Mybatis-Plus框架的入门快速构建以及基本的CRUD相关的操作说明。望可以帮助到有相关需求的伙伴。
    测试代码Github地址:https://github.com/yaokuku123/mybatis-demo

    1 Mybatis-Plus快速搭建

    本项目测试需要基于SpringBoot框架完成。

    1.1 创建并初始化数据库

    • 创建mybatis_plus数据库,并添加user表
    DROP TABLE IF EXISTS user;
    
    CREATE TABLE 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)
    );
    
    • 向user表中添加初始的字段用于测试
    DELETE FROM user;
    
    INSERT INTO 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');
    

    1.2 初始化Maven工程,并引入依赖

    注意:引入 MyBatis-Plus 无需再引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
    

    1.3 主配置类中的配置

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

    1.4 编写代码

    • 主启动类

    注意:在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹。

    package com.yqj;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    @MapperScan("com.yqj.mapper")
    public class MybatisPlusApplication {
        public static void main(String[] args) {
            SpringApplication.run(MybatisPlusApplication.class,args);
        }
    }
    
    
    • 实体类
    package com.yqj.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
    
    • mapper

    注意:让UserMapper接口继承mybatisplus中的BaseMapper<User>接口

    package com.yqj.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.yqj.entity.User;
    
    @Repository
    public interface UserMapper extends BaseMapper<User> {
    }
    
    

    1.5 测试

    package com.yqj;
    
    import com.yqj.entity.User;
    import com.yqj.mapper.UserMapper;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class MyTest {
    
        @Autowired
        private UserMapper userMapper;
    
        @Test
        public void testSelectList(){
            List<User> users = userMapper.selectList(null);
            for (User user : users) {
                System.out.println(user);
            }
        }
    }
    
    

    输出:说明成功实现基于Mybatis-Plus的快速入门操作

    User(id=1, name=Jone, age=18, email=test1@baomidou.com)
    User(id=2, name=Jack, age=20, email=test2@baomidou.com)
    User(id=3, name=Tom, age=28, email=test3@baomidou.com)
    User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
    User(id=5, name=Billie, age=24, email=test5@baomidou.com)
    

    2. Mybatis-Plus的CRUD相关操作

    基于之前搭建的快速搭建的程序测试CRUD的相关操作

    2.1 insert

    • 插入操作

    注意:数据库插入id值默认为:ID_WORKER 全局唯一id

    //插入用户数据
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("yorick");
        user.setAge(18);
        user.setEmail("yorick@qq.com");
        int result = userMapper.insert(user);
        System.out.println(result);
    }
    
    • 主键生成策略
    1.IdType.AUTO 主键自增策略
    2.IdType.ID_WORKER 若主键为数值型,Mybatis-Plus默认使用的策略
    3.IdType.ID_WORKER_STR 若主键为字符串型,Mybatis-Plus默认使用的策略
    4.IdType.INPUT 主键id需要手动输入
    5.IdType.NONE 默认跟随全局策略
    6.IdType.UUID 生成UUID
    

    在实体类的主键上增加主键生成策略的字段注解即可

    @TableId(type = IdType.AUTO)
    private Long id;
    

    2.2 update

    • 根据id更新
    //更新用户数据
    @Test
    public void testUpdate(){
        User user = userMapper.selectById(1L);
        user.setName("alice");
        int result = userMapper.updateById(user);
        System.out.println(result);
    }
    
    • 自动填充

    项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作。

    测试:

    1. 在数据库中添加两个datetime类型的新字段 create_time、update_time
    ALTER TABLE `user` ADD COLUMN `create_time` datetime
    ALTER TABLE `user` ADD COLUMN `update_time` datetime
    
    1. 在对应实体类的属性上添加注解
    //在插入时自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    //在插入和更新时自动填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
    1. 实现元对象处理器接口
    package com.yqj.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 {
        //设置执行插入时,自动填充的内容
        @Override
        public void insertFill(MetaObject metaObject) {
            this.setFieldValByName("createTime",new Date(),metaObject);
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    
        //设置执行更新时,自动填充的内容
        @Override
        public void updateFill(MetaObject metaObject) {
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    }
    
    
    1. 测试
    //插入用户数据
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("yorick2");
        user.setAge(19);
        user.setEmail("yorick2@qq.com");
        int result = userMapper.insert(user);
        System.out.println(result);
    }
    
    • 乐观锁

    当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。

    乐观锁实现方式:

    • 取出记录时,获取当前version
    • 更新时,带上这个version
    • 执行更新时, set version = newVersion where version = oldVersion
    • 如果version不对,就更新失败

    测试:

    1. 数据库添加version字段
    ALTER TABLE `user` ADD COLUMN `version` INT
    
    1. 实体类的对应属性上添加注解
    @Version
    @TableField(fill = FieldFill.INSERT) //设置插入时自动填充
    private Integer version;
    
    1. 元对象处理器接口添加version的insert默认值
    @Override
    public void insertFill(MetaObject metaObject) {
        ......
        this.setFieldValByName("version", 1, metaObject);
    }
    
    1. 注册乐观锁的配置插件

    另外,将原来标注在主启动类上的 @MapperScan 注解转移到配置类上面

    package com.yqj.config;
    
    import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @MapperScan("com.yqj.mapper")
    public class MybatisPlusConfig {
        
        //乐观锁插件
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor(){
            return new OptimisticLockerInterceptor();
        }
    }
    
    
    1. 测试

    将id为1的记录中version字段改为1,然后执行测试发现结果为2,说明乐观锁配置成功。

    //更新用户数据
    @Test
    public void testUpdate(){
        User user = userMapper.selectById(1L);
        user.setName("alice2");
        int result = userMapper.updateById(user);
        System.out.println(result);
    }
    

    2.3 select

    • 根据id查询记录
    //根据id查询
    @Test
    public void testSelectById(){
        User user = userMapper.selectById(1L);
        System.out.println(user);
    }
    
    • 多个id批量查询
    //多个id批量查询
    @Test
    public void testSelectBatchIds(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    • map封装的条件查询

    注意:map中的key对应的是数据库中的列名。例如数据库user_id,实体类是userId,这时map的key需要填写user_id

    //map封装的条件查询
    @Test
    public void testSelctByMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("name","yorick");
        map.put("age",18);
        List<User> users = userMapper.selectByMap(map);
        for (User user : users) {
            System.out.println(user);
        }
    }
    
    • 分页查询

    最终通过page对象获取相关数据

    测试:

    1. 在配置类中添加分页插件
    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
    
    1. 测试selectPage分页
    //分页查询
    @Test
    public void testSelectPage(){
        Page<User> page = new Page<>(1, 3); 
        userMapper.selectPage(page, null);
        page.getRecords().forEach(System.out::println); //当前页的数据
        System.out.println(page.getCurrent()); //当前页
        System.out.println(page.getPages()); //总页数
        System.out.println(page.getSize()); //每页显示的数据条目
        System.out.println(page.getTotal()); //总共的数据条目
        System.out.println(page.hasNext()); //是否有下一页
        System.out.println(page.hasPrevious()); //是否有上一页
    }
    

    2.4 delete

    物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

    逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

    • 根据id删除
    //根据id删除
    @Test
    public void testDeleteById(){
        int result = userMapper.deleteById(5L);
        System.out.println(result);
    }
    
    • 根据id批量删除 deleteBatchIds()

    • 根据map删除 deleteByMap()

    • 逻辑删除

    测试:

    1. 数据库中添加 deleted字段,用于表示逻辑删除
    ALTER TABLE `user` ADD COLUMN `deleted` boolean
    
    1. 实体类的对应属性上面添加逻辑删除的注解
    @TableLogic
    @TableField(fill = FieldFill.INSERT) //插入时自动填充
    private Integer deleted;
    
    1. 元对象处理器接口添加deleted的insert默认值
    @Override
    public void insertFill(MetaObject metaObject) {
        ......
        this.setFieldValByName("deleted", 0, metaObject);
    }
    
    1. 在配置类中注册逻辑删除的插件
    //逻辑删除
    @Bean
    public ISqlInjector iSqlInjector(){
        return new LogicSqlInjector();
    }
    
    1. 测试逻辑删除

    将id为4的记录中deleted字段改为0,然后执行测试发现其变为1,说明逻辑删除成功。

    • 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
    • 测试后分析打印的sql语句,是一条update
    • MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断
    • 注意:被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作
    //根据id删除
    @Test
    public void testDeleteById(){
        int result = userMapper.deleteById(4L);
        System.out.println(result);
    }
    

    2.5 性能分析

    性能分析拦截器,用于输出每条 SQL 语句及其执行时间

    SQL 性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题

    测试:

    1. 在配置类中添加性能分析的插件
    //性能分析
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启
    public PerformanceInterceptor performanceInterceptor() {
        //参数:maxTime: SQL 执行最大时长,超过自动停止运行,有助于发现问题
        //参数:format: SQL是否格式化,默认false
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(500);//ms,超过此处设置的ms则sql不执行
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
    
    1. SpringBoot中设置为dev开发环境
    #环境设置:dev、test、prod
    spring.profiles.active=dev
    
    1. 测试
    //插入用户数据
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("yorick");
        user.setAge(20);
        user.setEmail("yorick@qq.com");
        int result = userMapper.insert(user);
        System.out.println(result);
    }
    

    结果:显示出插入的性能为4ms

    Time:4 ms - ID:com.yqj.mapper.UserMapper.insert
    Execute SQL:
        INSERT 
        INTO
            user
            ( id, name, age, email, create_time, update_time, version, deleted ) 
        VALUES
            ( 1298135534432567298, 'yorick', 20, 'yorick@qq.com', '2020-08-25 13:50:04', '2020-08-25 13:50:04', 1, 0 )
    

    2.6 复杂查询

    //复杂查询
    @Test
    public void testComplexSelect(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
    
        //ge,gt,le,lt,isNull,isNotNull
        //查询年龄不小于20岁的用户
        //wrapper.ge("age",20);
    
        //eq,ne
        //查询姓名为yorick的用户
        //wrapper.eq("name","yorick");
    
        //between,notBetween
        //查询年龄在20~30之间的用户,包含20和30边界
        //wrapper.between("age",20,30);
    
        //like
        //查询姓名包含yorick的用户
        //wrapper.like("name","yorick");
    
        //orderByDesc,orderByAsc
        //按id降序排序
        //wrapper.orderByDesc("id");
    
        //last 直接拼接sql到最后,有sql注入风险
        //wrapper.last("limit 1");
    
        //指定要查找的列
        wrapper.select("id","name");
    
    
        List<User> users = userMapper.selectList(wrapper);
        for (User user : users) {
            System.out.println(user);
        }
    }
    

    相关文章

      网友评论

          本文标题:Mybatis-Plus使用与配置

          本文链接:https://www.haomeiwen.com/subject/ecfzjktx.html