• MyBatisPlus的学习


    MyBatisPlus

    1.简介

    官网:MyBatis-Plus (baomidou.com)

    使用第三方组件:

    1.导入对应的依赖

    2.研究依赖如何配置

    3.代码如何编写

    4.提高扩展技术能力

    步骤:

    1.创建数据库mybatis_plus

    2.创建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)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.插入数据

    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
    • 3
    • 4
    • 5
    • 6

    4.编写项目,初始化项目,使用springboot初始化!

    5.导入依赖

    不用同时导入mybatis和mybatis-plus

    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.29version>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <version>1.18.24version>
    dependency>
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.0.5version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.连接数据库

    # mysql 5 驱动不同 com.mysql.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=123456789
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    
    # mysql 8 需要时区的配置 serverTimezone=GMT%2B8 驱动不同 com.mysql.cj.jdbc.Driver
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7.传统:pojo-dao-service-controller

    使用mybatis-plus后:

    • pojo
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
    
        private Long id;
        private String name;
        private String email;
        private Integer age;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • mapper接口
    //在对应的mapper上面实现基本的接口
    @Repository //持久层
    public interface UserMapper extends BaseMapper<User> {
        //所有的crud操作都自动编写了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 使用
    @SpringBootTest
    class MybatisPlusApplicationTests {
    
        //继承了basemapper,所有方法都来自父类
        @Autowired
        private UserMapper userMapper;
    
        @Test
        void contextLoads() {
            //查询全部用户,参数是一个wrapper,条件构造器(无条件就为null)
            List<User> users = userMapper.selectList(null);
            users.forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 注意点,需要在主启动类上扫描所有的mapper类
    @SpringBootApplication
    @MapperScan("com.liu.mapper")  //扫描mapper文件夹
    
    • 1
    • 2

    2.配置日志

    现在的sql是不可见的,需要通过日志来查看sql语句!

    配置:

    # 配置日志
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2

    在这里插入图片描述

    3.CRUD扩展

    插入操作

    //测试插入
        @Test
        public void testInsert(){
            User user = new User();
            user.setName("llx");
            user.setAge(20);
            user.setEmail("97122@qq.com");
            int insert = userMapper.insert(user);
            System.out.println(insert);
            System.out.println(user); //自动生成了id
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    数据库插入的id默认值为:全局的唯一id

    主键生成策略

    默认方案:全局唯一id

    @TableId(type = IdType.ID_WORKER)
    
    • 1

    分布式系统唯一id生成

    雪花算法:

    snowflake是twitter开源的分布式id生成算法,结果是一个long型得到ID。

    核心思想是:使用41bit作为毫秒数,10bit作为机器ID,12bit作为毫秒内的流水号(每个节点在每毫秒开源产生4096个id),最后有一个符号位,永远是0。

    主键自增

    需要配置主键自增:

    1.实体类字段上@TableId(type = IdType.AUTO)

    2.数据库字段一定要是自增的!

    其余主键

    public enum IdType {
        AUTO(0), //id自增
        NONE(1), //未设置主键
        INPUT(2),//手动输入
        ID_WORKER(3),//默认的全局id
        UUID(4),//全局唯一id
        ID_WORKER_STR(5);//idworker 字符串表示法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    更新操作

     //测试更新
        @Test
        public void testUpdate(){
            User user = new User();
            user.setId(4L);
            user.setName("棒!");
            //自动拼接sql
            user.setAge(15);
            //updateById 但是参数是一个对象
            int update = userMapper.updateById(user);
            System.out.println(update);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    自动填充

    创建时间,修改时间,这些操作都是自动化完成的,不需要手动更新

    所有数据库表:gmt_create、gmt_modified几乎所有的表都要配置上,需要自动化!

    方式一:数据库级别

    1. 在表中新增字段 create_time,update_time

    在这里插入图片描述

    2.再次测试插入方法,需要先把实体类同步!

    方式二:代码级别

    1.删除数据库的默认值,更新操作!

    在这里插入图片描述

    2.实体类字段属性上添加注解!

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.编写处理器处理注解即可!

    package com.liu.handler;
    
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    
    @Slf4j
    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        //插入时的填充策略
        @Override
        public void insertFill(MetaObject metaObject) {
            log.info("start insert fill....");
            this.setFieldValByName("createTime",new Date(),metaObject);
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    
        //更新时的填充策略
        @Override
        public void updateFill(MetaObject metaObject) {
            log.info("start insert fill....");
            this.setFieldValByName("updateTime",new Date(),metaObject);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    4.乐观锁讲解

    乐观锁:无论干什么都不上锁,如果出了问题,再次更新测试值(version)

    悲观锁:无论干什么都上锁,再去操作!

    实现方式:

    1. 取出记录时,获取当前version

    2. 更新时,带上version

    3. 执行更新时,set version = new version where version = old version

    4. 如果version不对,就更新失败

    测试

    1.数据库增加字段

    在这里插入图片描述

    2.实体类加字段

    @Version //version 注解
    private Integer version;
    
    • 1
    • 2

    3.组件配置

    @MapperScan("com.liu.mapper")  //扫描mapper文件夹
    @EnableTransactionManagement
    @Configuration
    public class MyBatisPlusConfig {
        //注册乐观锁插件
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor(){
            return new OptimisticLockerInterceptor();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.测试

    //测试乐观锁
        @Test
        public void testOptimisticLocker(){
            //1.查询用户信息
            User user = userMapper.selectById(1L);
            //2.修改用户信息
            user.setName("liuxiang");
            user.setEmail("91@qq.com");
            //3.执行更新
            userMapper.updateById(user); //会带上乐观锁
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    查询

    //测试批量查询
        @Test
        public void testSelectById(){
            List<User> user = userMapper.selectBatchIds(Arrays.asList(1,2,3));
            user.forEach(System.out::println);
        }
    
     //条件查询 map
        @Test
        public void testSelectByBatchIds(){
            HashMap<String, Object> hashMap = new HashMap<>();
    //        hashMap.put("name","liuxiang");
            hashMap.put("age",24);
            List<User> userList = userMapper.selectByMap(hashMap);
            userList.forEach(System.out::println);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    分页查询

    1.组件配置

    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.直接使用Page对象即可!

    //分页查询
    @Test
    public void testPage(){
        //当前页 页面大小
        Page<User> page = new Page<>(1,3);
        userMapper.selectPage(page,null);
        page.getRecords().forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    删除

    //测试删除
    @Test
    public void testDelete(){
        userMapper.deleteById(1L);
    }
    //通过id批量删除
    @Test
    public void testDeleteBatchById(){
        userMapper.deleteBatchIds(Arrays.asList(1568154279481020417L,1568158270856126466L));
    }
    
    //通过map删除
    @Test
    public void testDeleteMap(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","llx");
        userMapper.deleteByMap(map);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    逻辑删除:在数据库中没有被移除,而是通过一个变量让他失效 deleted = 0 => deleted = 1

    测试:

    1.在数据库中增加一个字段

    在这里插入图片描述

    2.pojo实体类增加属性

    @TableLogic //逻辑删除
    private Integer deleted;
    
    • 1
    • 2

    3.配置

    //逻辑删除
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    #配置逻辑删除
    mybatis-plus.global-config.db-config.logic-delete-value=1
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    
    • 1
    • 2
    • 3

    4.测试(用户还在数据库,但是delete字段值变化了)

    在这里插入图片描述

    再次执行查询操作的时候,会自动拼接deleted字段,查询不到2号用户!

    5.性能分析插件

    1.dev测试环境

    spring.profiles.active=dev
    
    • 1

    2.配置插件

     //sql执行效率插件
        @Bean
        @Profile({"dev","test"}) //测试环境下开启
        public PerformanceInterceptor performanceInterceptor(){
            PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
            performanceInterceptor.setMaxTime(100);//最大sql运行时间ms
            performanceInterceptor.setFormat(true); //是否格式化
            return performanceInterceptor;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.条件构造器

     @Test
        void contextLoads(){
            //查询name不为空 的用户,并且邮箱不为空的用户,年龄大于25
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.isNotNull("name")
                    .isNotNull("email")
                    .ge("age",20);
            userMapper.selectList(wrapper).forEach(System.out::println)
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    eq : 等于
    gt : 大于
    ge : 大于等于
    ne : 不等于
    lt : 小于
    le : 小于等于
    between:在..之间
    isNull:非空
    like:'%值%'
    in:
    having:接sql语句
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    @Test
       void test2(){
           //查询name不为空 的用户,并且邮箱不为空的用户,年龄大于25
           QueryWrapper<User> wrapper = new QueryWrapper<>();
           wrapper.between("age",20,27);
           Integer c = userMapper.selectCount(wrapper);
           System.out.println(c);
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //模糊查询
        @Test
        void test3(){
            //查询name不为空 的用户,并且邮箱不为空的用户,年龄大于25
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper
                    .like("name","o")
                    .likeLeft("email","t");
            List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
            maps.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    @Test
        void test4(){
            //查询name不为空 的用户,并且邮箱不为空的用户,年龄大于25
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            //在子查询中查
            wrapper.inSql("id","select id from user where id<3");
            List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
            maps.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @Test
        void test5(){
            //降序排序
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.orderByDesc("id");
            List<User> userList = userMapper.selectList(wrapper);
            userList.forEach(System.out::println);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.代码生成器

    旧:

     // 代码生成器
            AutoGenerator mpg = new AutoGenerator();
    
            // 全局配置
            GlobalConfig gc = new GlobalConfig();
            String projectPath = System.getProperty("user.dir");
            gc.setOutputDir(projectPath + "/src/main/java");
            gc.setAuthor("llx");
            gc.setOpen(false);
    		gc.setFileOverride(false);
            gc.setIdType(IdType.ID_WORKER);
    		gc.setDateType(DateType.ONLY_DATE);
            mpg.setGlobalConfig(gc);
    
            // 数据源配置
            DataSourceConfig dsc = new DataSourceConfig();
            dsc.setUrl("jdbc:mysql://localhost:3306/ant?useUnicode=true&useSSL=false&characterEncoding=utf8");
            // dsc.setSchemaName("public");
            dsc.setDriverName("com.mysql.jdbc.Driver");
            dsc.setUsername("root");
            dsc.setPassword("密码");
    		dsc.setDbType(DbType.MYSQL);
            mpg.setDataSource(dsc);
    
            // 包配置
            PackageConfig pc = new PackageConfig();
            pc.setModuleName(scanner("模块名"));
            pc.setParent("com.liu");
    		pc.setEntity("pojo");
    		pc.setMapper("mapper");
    		pc.setService("service");
            mpg.setPackageInfo(pc);
    
            // 策略配置
            StrategyConfig strategy = new StrategyConfig();
            strategy.setNaming(NamingStrategy.underline_to_camel);
             strategy.setColumnNaming(NamingStrategy.underline_to_camel);
    		strategy.setInclude("user"); //设置要映射的表名,可以多个参数
            strategy.setEntityLombokModel(true);
    		//驼峰命名风格
            strategy.setRestControllerStyle(true);
           	strategy.setLogicDeleteFieldName("deleted");
    		//自动填充配置
    		TableFill gmtCreate = new TableFill("gmt_create",FieldFill.INSERT);
    		TableFill gmtModified = new TableFill("gmt_modified",FieldFill.INSERT_UPDATE);
    		ArrayList<TableFill> tableFills = new ArrayList<>();
    		tableFills.add(gmtCreate);
    		tableFills.add(gmtModified);
    		strategy.setTableFillList(tableFills);
    		//乐观锁
    		strategy.setVersionFieldName("version");
    		
            mpg.setStrategy(strategy);
            mpg.setTemplateEngine(new FreemarkerTemplateEngine());
            mpg.execute();
            };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    trategy.setRestControllerStyle(true);
    strategy.setLogicDeleteFieldName(“deleted”);
    //自动填充配置
    TableFill gmtCreate = new TableFill(“gmt_create”,FieldFill.INSERT);
    TableFill gmtModified = new TableFill(“gmt_modified”,FieldFill.INSERT_UPDATE);
    ArrayList tableFills = new ArrayList<>();
    tableFills.add(gmtCreate);
    tableFills.add(gmtModified);
    strategy.setTableFillList(tableFills);
    //乐观锁
    strategy.setVersionFieldName(“version”);

        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
        };
    
    • 1
    • 2
    • 3
    • 4
    
    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    ELK-介绍及Elasticsearch集群搭建
    基于elasticjob的入门maven项目搭建
    Python入门进阶:68 个 Python 内置函数详解
    caffe 统计分析显示权重分布脚本
    跨文档通信
    求算法工程师做访谈 绝对真实
    C语言-二级指针应用场景
    vulnhub Vegeta: 1
    【项目实战:核酸检测平台】第二章 大卸八块
    【教3妹学编程-java基础6】详解父子类变量、代码块、构造函数执行顺序
  • 原文地址:https://blog.csdn.net/llx522/article/details/126790120