MybatisPlus

本文详细介绍了MyBatisPlus在SpringBoot项目中的使用,包括快速入门、连接数据库、数据操作(新增、更新、逻辑删除、分页查询等),特别是乐观锁的实现,以及条件构造器的应用,帮助开发者理解MyBatisPlus如何简化数据库操作。
摘要由CSDN通过智能技术生成

MyBatisPlus

  • 在真实开发中 在表的字段中还会存在:
  • version(乐观锁),deleted(逻辑删除),created和updated(时间);
快速入门
创建一个springboot项目
  • 导入依赖:

  • <!--        数据库驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    
    <!--  mybatis-plus自己开发的      -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.0.5</version>
            </dependency>
    
    
连接数据库

关于主键id :ID_WORKER //默认的全局唯一id(雪花算法)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9TSVbBT-1644408533648)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215221812729.png)]

  • @TableId(type = IdType.AUTO)  //对应数据库中的id也要自增;
                    IdType.NONE //未设置主键
                    IdType.INPUT //手动输入
                           UUID //全局唯一id UUID
                           ID_WORKER //默认的全局唯一id
                           ID_WORKER_str//ID_WORKER字符串表示法
    
数据据操作

核心: -在mapper层继承父接口baseMapper,然后调用父接口中的方法实现CRUD;

泛型一定要写,是表对应的pojo对象;

  • public interface UserMapper extends BaseMapper<User>
    
新增
  •  @Test
        void test1(){
            //测试插入数据
            User user=new User();        user.setUsername("lang").setAge(18).setEmail("222@qq.com");
            userMapper.insert(user);
        }
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mlVGNKtx-1644408533652)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215222838204.png)]

更新
  • 通过条件自动拼接动态sql

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZahFBvul-1644408533653)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215222938006.png)]

  •   @Test
        void test2(){
            User user=new User();
            user.setId(5L);//id=5
            user.setUsername("王祖贤");
            //注意需要传入的是对象;
            userMapper.updateById(user);
        }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bbiKBVQN-1644408533653)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215223529148.png)]

补充:自动填充
  • 创建时间 修改时间:让它们自动的生成填充 而不是手动添加;

  • 一:在表中创建对应的字段

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hPz3Cwqm-1644408533654)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215224337484.png)]

  • 二:添加注解

  •     //创建时更新
         @TableField(fill = FieldFill.INSERT)
          private Date created;
         //创建和更改时更新
         @TableField(fill = FieldFill.INSERT_UPDATE)
          private Date updated;
    
    
  • 编写处理器

  • 实现MetaObjectHandler接口;

  • @Component
    @Slf4j  //添加日志注解
    public class ObjectHandler implements MetaObjectHandler {
        //插入时的填充策略;
        @Override
        public void insertFill(MetaObject metaObject) {
             log.info("开始执行插入填充..");
           this.setFieldValByName("created", new Date(), metaObject);
           this.setFieldValByName("updated", new Date(), metaObject);
    
    
        }
        //更新时的填充策略;
        @Override
        public void updateFill(MetaObject metaObject) {
           log.info("开始执行更新填充..");
           this.setFieldValByName("updated", new Date(), metaObject);
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpeQaoMQ-1644408533654)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215230145595.png)]

乐观锁
  • 乐观锁:顾名思义,比较乐观,它总是认为不会出现问题,无论什么操作都不去上锁,如果出现问题,再次更新值进行测试:version
    • 乐观锁适用于写比较少的情况下(多读场景)
  • 悲观锁:十分悲观,认为什么操作都可能出现问题,无论干什么都会上锁,再去操作;
    • 一般多写的场景下用悲观锁就比较合适

  • 当要更新一条记录的时候,希望这条记录没有被别人更新
    乐观锁实现方式:

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

    举例

  • 乐观锁:1.先查询,获得版本号
          2.更新时 同时要把版本号进行更新,一般加1   
    --A      
      update user set name="li",version=version+1
      where id=2 and version=1
      
      
     --B 如果B线程抢先完成,此时version=2,会导致A线程修改失败;     
      update user set name="li",version=version+1
      where id=2 and version=1 
      
      
    

测试

  • 1.在表中增加字段;

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XtWbL6Rb-1644408533655)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215232036691.png)]

  • 2.同步实体类,增加注解

  •      @Version  //代表乐观锁;
         private Integer version;
    
  • 3.注册乐观锁插件

  • @Configuration  //标记配置类
    @EnableTransactionManagement //管理事务,默认开启
    @MapperScan("com.jt.mapper")
    public class MyBatisPlusConfig {
    
       //注册乐观锁插件  官方文档 版本3.4.3
        @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
           MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
           interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
    
    }
    
    
  • 4.测试乐观锁

  • @Test
        void test3(){
            //测试乐观锁成功
            //单线程情况 更改数据信息
            //1.查询用户信息
            User user = userMapper.selectById(2);
            //2.修改用户信息
            user.setUsername("刘亦菲").setEmail("899@qq.com");
            //3.执行更新
            userMapper.updateById(user);
        }
    
  • 输出结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B5GmvRfU-1644408533655)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215234103756.png)]

  • 测试乐观锁失败的案例

  •  @Test
        void test4(){
            //测试乐观锁执行失败
            //1.线程A执行操作数据
            User user = userMapper.selectById(3);
            user.setUsername("刘亦菲").setEmail("899@qq.com");
      
            //2.线程A还未执行完,线程B插队执行;
            User user2 = userMapper.selectById(3);
            user2.setUsername("刘诗诗").setEmail("999@qq.com");
            userMapper.updateById(user2);
      
            //线程A未执行 更新;
            userMapper.updateById(user);
      
        }
    

    结果分析

    • 2次查询更改都是通过version=2去进行操作,但是线程B操作完之后,version的值已经变成3
    • 所以线程A的操作就会失效;
    • 如果没有乐观锁那么线程B的值就会被覆盖;
    • 多线程下一定要加锁;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T0EdtL3j-1644408533655)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215235236027.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vtmYeu9C-1644408533656)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211215235631045.png)]

测试2
  • 需求:查询id=1,2,3的用户信息;

  •  @Test
        void test5(){
            //参数是集合,所以需要通过asList将数组转换为集合;
            List<User> list = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
            //将结果遍历输出;
            list.forEach(System.out::println);
      
        }
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IBdqYi2u-1644408533656)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211217201150557.png)]

  • 查询姓名为刘亦菲,年龄为20的用户信息;

  •  @Test
        void test6(){
            Map map=new HashMap();
            map.put("username", "刘亦菲");
            map.put("age", 20);
      
            List users = userMapper.selectByMap(map);
            users.forEach(System.out::println);
      
        }
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AK2senl3-1644408533657)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211217203030114.png)]

分页查询
导入插件
  •  //配置分页插件;
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor2() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
            return interceptor;
        }
    
  • @Test
        void test7(){
            //1.设置当前页,和每页用户数;
            Page<User> page=new Page<>(2,5);
            userMapper.selectPage(page, null);
            //打印记录;
            page.getRecords().forEach(System.out::println);
            //获取总用户数;
            System.out.println(page.getTotal());
        }
    
删除
  •  @Test
        void test9(){
            Map map=new HashMap();
            map.put("id", "1471119629576306691");
            map.put("age","18");
            userMapper.deleteByMap(map);
      
        }
    
逻辑删除
  • 物理删除:从数据库中直接删除
  • 逻辑删除:在数据库中没有删除,而是通过一个变量使其失效;
    • 管理员可以查看被删除的记录
    • 防止数据的丢失,类似于回收站;
  • 1在表中增加字段

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tbIARZrg-1644408533657)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211217212144659.png)]

  • 2在pojo对象增加属性

  • //逻辑删除注解
         @TableLogic
         private Integer deleted;
    
  • 3配置插件

 global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤                         2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

  •  @Test
        void test01(){
      
            userMapper.deleteById("1471119629576306690");
        }
    
  • 测试结果:实际上是走的更新操作;

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UMzxRyHV-1644408533658)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211217213450753.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XwMGoasa-1644408533659)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211217213536528.png)]

  • 注意:虽然数据在数据库中但是并不能进行操作;比如查询,更改;
条件构造器
  • 用于复杂条件下的查询,书写复杂的sql语句;

  • 测试一:

  • @Test
        void  test1(){
            //测试1:查询姓名不为null,邮箱不为null,年龄大于18的用户
            QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
            queryWrapper.isNotNull("username")
                    .isNotNull("email").
                    gt("age", 18);
            userMapper.selectList(queryWrapper).forEach(System.out::println);
        }
    
    
  • 测试二

  •  @Test
        void test2(){
            //测试二 查询年龄在20岁到30岁之间的用户数
            QueryWrapper<User> queryWrapper=new QueryWrapper<>();
            queryWrapper.between("age", 20, 30);
            Integer integer = userMapper.selectCount(queryWrapper);
            System.out.println(integer);
        }
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9m8JRs63-1644408533660)(C:\Users\86131\AppData\Roaming\Typora\typora-user-images\image-20211217223002104.png)]

  • 测试三

  •  @Test
        void test3(){
            //本类测试模糊查询
            QueryWrapper<User> queryWrapper=new QueryWrapper<>();
            queryWrapper.notLike("username", "刘")
                    .likeRight("email", "2");
            List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
            maps.forEach(System.out::println);
      
        }
      
    

}


- [外链图片转存中...(img-9m8JRs63-1644408533660)]

- 测试三

- ```java
 @Test
    void test3(){
        //本类测试模糊查询
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.notLike("username", "刘")
                .likeRight("email", "2");
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        maps.forEach(System.out::println);
  
    }
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值