MyBatis-Plus学习笔记——02CRUD

一. 插入

1. insert: 插入

1. 案例
  1. 方式1

    @Test
    void test01(){
        User user = new User(8L, "user08", 23, "user08@qq.com");
        userMapper.insert(user);
    }
    
  2. 方式2

    @Test
    void test02(){
        User user = new User();
        user.setName("user02");
        user.setAge(8);
        user.setEmail("user02@qq.com");
        // 自动生成id
        userMapper.insert(user);
    }
    

    在这里插入图片描述

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

2. 主键生成策略

1. 雪花算法
  1. 说明

    SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的

    这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。

  2. 案例

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        /**
         * IdType.AUTO: 数据库ID自增 (数据库字段一定要设置为自增的, 否则会报错)
         * IdType.NONE: 未设置主键
         * IdType.INPUT: 手动输入, 一旦手动输入id后, 就需要自己配置id了
         * IdType.ID_WORKER: 默认的全局ID(数字)
         * IdType.UUID: 全局唯一ID uuid
         * IdType.ID_WORKER_STR: ID_WORKER的字符串(字符串)
         */
        @TableId(type = IdType.AUTO)
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    

二. 修改

1. update: 修改

  1. 案例

    // 通过id更改
    @Test
    public void test03(){
        User user = new User();
        // 通过条件动态拼接SQL
        user.setId(8L);
        user.setName("user1");
        user.setEmail("user1@qq.com");
        // updateById的参数是一个对象
        userMapper.updateById(user);
    }
    

2. 自动填充

创建时间, 修改时间, 这些操作一般都是自动化完成的, 我们不希望手动更新.

1. 数据库级别(工作中不允许修改数据库)
  1. 在表中新增create_time, update_time
    在这里插入图片描述

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

    private Date createTime;
    private Date updateTime;
    
  3. 测试

    @Test
    void test02(){
        User user = new User();
        user.setName("user03");
        user.setAge(8);
        user.setEmail("user03@qq.com");
        userMapper.insert(user);
    }
    

    在这里插入图片描述

    @Test
    public void test03(){
        User user = new User();
        // 通过条件动态拼接SQL
        user.setId(6L);
        user.setName("user1");
        user.setEmail("user1@qq.com");
        // updateById的参数是一个对象
        userMapper.updateById(user);
    }
    

    在这里插入图片描述

2. 代码级别
  1. 删除数据库中的设置
    在这里插入图片描述

  2. 实体类上的属性增加注解

    // 字段添加填充内容
    // 插入的时候自动操作
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    // 插入或更新的时候自动操作
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
  3. 编写处理器来处理这个注解

    @Slf4j
    @Component  // 一定不要忘记把处理器加到IOC容器中
    public class MyMetaObjectHandler implements MetaObjectHandler {
        // 插入时的填充策略
        @Override
        public void insertFill(MetaObject metaObject) {
            log.info("start insert fill...");
            // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
            this.setFieldValByName("createTime", new Date(), metaObject);
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    
        // 更新时的填充策略
        @Override
        public void updateFill(MetaObject metaObject) {
            log.info("start update fill...");
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    }
    

3. 乐观锁

1. 说明
  1. 乐观锁:

    顾名思义十分乐观, 它总是认为不会出现问题, 无论干什么不去上锁! 如果出现了问题, 再次更新值测试

  2. 悲观锁:

    顾名思义十分悲观, 它总是认为总会出现问题, 无论干什么都会上锁! 再去操作!

2. 乐观锁实现方式
  1. 取出记录时, 获取当前的version

  2. 更新时, 带上这个version

  3. 执行更新时, set version = newVersion Where version = oldVersion

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

    乐观锁: 1. 先查询, 获得版本号: version = 1
    --A
    update user set name = "hjf", version = version + 1
    where id = 2 and version = 1
    
    --B线程抢先完成, 这个时候version=2, 会导致A修改失败
    update user set name = "hjf", version = version + 1
    where id = 2 and version = 1
    
3. 乐观锁插件
  1. 给数据库添加一个version字段, 初始值为1
    在这里插入图片描述

  2. 实体类添加属性

    @Version //乐观锁Version注解
    private Integer version;
    
  3. 注册组件

    // 可以将主启动类上面的MapperScan注解, 添加到这里
    @MapperScan("com.hjf.mapper")   // 扫描mapper文件夹
    @EnableTransactionManagement    // 自动开启事务的注解
    @Configuration  // 配置类
    public class MyBatisPlusConfig {
        // 注册乐观锁插件
        @Bean
        public OptimisticLockerInterceptor optimisticLockerInterceptor() {
            return new OptimisticLockerInterceptor();
        }
    }
    
  4. 测试

    1. 测试乐观锁成功!

      @Test
      public void testOptimisticLocker1(){
          // 1. 查询用户信息
          User user = userMapper.selectById(6L);
          // 2. 修改用户信息
          user.setName("用户02");
          user.setEmail("user01@gmail.com");
          // 3. 执行更新操作
          userMapper.updateById(user);
      
      }
      

      在这里插入图片描述

      在这里插入图片描述

    2. 测试乐观锁失败!

      @Test
      public void testOptimisticLocker2(){
          // 线程1
          User user1 = userMapper.selectById(7L);
          user1.setName("用户001");
          user1.setEmail("user001@gmail.com");
          // 模拟另一个线程执行了插队操作
          User user2 = userMapper.selectById(7L);
          user2.setName("用户002");
          user2.setEmail("user002@gmail.com");
          userMapper.updateById(user2);
          //如果没有乐观锁, 这回覆盖插队线程的值, 有乐观锁, 则执行失败
          userMapper.updateById(user1);	
      }
      

      user1修改失败
      在这里插入图片描述
      只有user2修改成功
      在这里插入图片描述

三. 查询

1. insert: 查询

  1. 通过id查询

    // 通过id查询
    @Test
    public void testSelectById(){
        User user = userMapper.selectById(7L);
        System.out.println(user);
    }
    
  2. id批量查询

    // id批量查询
    @Test
    public void testSelectBatchByIds(){
        List<User> userList = userMapper.selectBatchIds(Arrays.asList(5, 6, 7));
        userList.forEach(System.out::println);
    }
    
  3. 按条件查询map

    // 按条件查询: map
    @Test
    public void testSelectByMap(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "用户002");
        map.put("age", 8);
        // SELECT * FROM user WHERE name = ? AND age = ?
        List<User> userList = userMapper.selectByMap(map);
        userList.forEach(System.out::println);
    }
    

2. 分页查询

1. 方式
  1. 原始的limit进行分页
  2. pageHelper第三方插件
  3. Mybatis-plus也内置了分页插件
2. 分页插件
  1. 配置拦截器组件

    // 注册分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
    
  2. 使用

    @Test
    public void testPage(){
        /**
             * 参数1: 当前页
             * 参数2: 页面大小
             */
        Page<User> page = new Page<>(2, 3);
        IPage<User> userIPage = userMapper.selectPage(page, null);
        System.out.println("------------------------");
        // 获取当前页信息
        page.getRecords().forEach(System.out::println);
        userIPage.getRecords().forEach(System.out::println);
        System.out.println("------------------------");
        // 获取数据总数
        System.out.println(page.getTotal());
        System.out.println(userIPage.getTotal());
    }
    

四. 删除

1. delete: 删除

  1. 通过id

    // 根据id删除
    @Test
    public void testDeleteById(){
        userMapper.deleteById(7L);
    }
    
  2. 批量删除

    // 批量参数
    @Test
    public void testDeleteBatchIds(){
        userMapper.deleteBatchIds(Arrays.asList(3,4));
    }
    
  3. 条件删除

    @Test
    public void testDeleteByMap(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "用户002");
        userMapper.deleteByMap(map);
    }
    

2. 逻辑删除

物理删除: 从数据库中直接删除

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

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

    在这里插入图片描述

  2. 实体类中增加属性

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

    // 逻辑删除组件
    @Bean
    public ISqlInjector iSqlInjector(){
        return new LogicSqlInjector();
    }
    
  4. 配置文件

    # 配置逻辑删除
    # 删除后的值
    mybatis-plus.global-config.db-config.logic-delete-value=1
    # 没有删除时的值
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    
  5. 测试

    @Test
    public void testDeleteById(){
        userMapper.deleteById(5L);
    }
    

    在这里插入图片描述

  6. 通过id 和 deleted = 1都不能查询到被逻辑删除后的数据

    @Test
    public void testSelectById(){
        User user = userMapper.selectById(5L);
        System.out.println(user);
    }
    

    在这里插入图片描述

    @Test
    public void testSelectByMap(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("deleted", 1);
        List<User> userList = userMapper.selectByMap(map);
        userList.forEach(System.out::println);
    }
    

    在这里插入图片描述

说明:

  1. 本文参考了狂神的Mybatis-Plus的课程
  2. 课程链接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值