1-复习Mybatis-Plus


本项目是一个在线教育项目,采用前后端分离技术,技术栈如下:

  • 前端: Vue、Element-ui、Axios、Node.js …
  • 后端:SpringBoot、SpringCloud、Mybatis-Plus、SpringSecurity、Redis、Maven、EasyExcel、JWT、OAuth2 …
  • 其他:阿里云OSS、阿里云视频点播服务、腾讯云短信服务、微信登录和支付、Docker、Git、Jenkins、Nginx …

今天主要复习Mybatis-Plus(MP),因为持久层技术是本项目的重点之一。

创建数据库表

DROP TABLE IF EXISTS `user`;
create table user
(
    id          bigint auto_increment comment '主键ID' primary key,
    name        varchar(30) null comment '姓名',
    age         int         null comment '年龄',
    email       varchar(50) null comment '邮箱',
    create_time datetime    null comment '创建时间',
    update_time datetime    null comment '修改时间',
    version     int         null comment '版本(测试乐观锁)'
);

新建SpringBoot工程并引入依赖、编写配置文件

<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>
    </dependency>

    <!-- MP依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.3.4</version>
    </dependency>

    <!-- MySql依赖 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- lombok依赖 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
 </dependencies>
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus1?serverTimezone=GMT%2B8
    username: root
    password: root

# 查看sql执行过程
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

entity、mapper

@Data
public class User {
    // 主键生成策略:自增 
    @TableId(type = IdType.AUTO)
    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;
}
@Mapper     // 不加该注解在测试类的@Autowired中会报错
public interface UserMapper extends BaseMapper<User> {

}

Mybatis-Plus测试

  1. 查询所有数据
    @Autowired
    private UserMapper userMapper;
        
    // 查询user表中的所有数据
    @Test
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        System.out.println(users);
    }
  2. 添加数据
    // mp实现添加操作
    @Test
    void addUser()
        User user = new User();
        user.setName("Prannt");
        user.setAge(12);
        user.setEmail("prannt@qq.com");
        int insert = userMapper.insert(user);
        System.out.println("insert = " + insert
  3. 修改数据
    // update
    @Test
    void updateUser()
        User user = new User();
        user.setId(1461239461974220801L);
        user.setAge(130);
        int row = userMapper.updateById(user);
        System.out.println(row);
    }
  4. 测试乐观锁
    • 在实体类的字段上添加注解
      @Version
      @TableField(fill = FieldFill.INSERT)
      private Integer version;
    • 配置乐观锁插件
      package com.atguigu.mpdemo1010.config;
      
      @Configuration
      @MapperScan("com.atguigu.mpdemo1010.mapper")  // 扫描到mapper接口所在的包
      public class MpConfig {
          // 配置乐观锁插件
          @Bean
          public MybatisPlusInterceptor mybatisPlusInterceptor() {
              MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
              interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
              return interceptor;
          }
      }
    • 给version字段添加初始值
      package com.atguigu.mpdemo1010.handler;
      
      @Component  
      public class MyMetaObjectHandler implements MetaObjectHandler {
          @Override
          public void insertFill(MetaObject metaObject) {
              // 为版本号添加初始值
              this.setFieldValByName("version",1,metaObject);     
          }
      }
    • 测试
      @Test
      void testOptimisticLocker(){
          // 先查再改
          // 根据id查询数据
          User user = userMapper.selectById(1461239461974220804l);
          // 修改查查来的这条数据
          user.setAge(200);
          userMapper.updateById(user);
          // 每修改一次,version +1,因为我已经修改3次了,所以version为3
      }
    • 结果
  5. 多个id批量删除(用的不多)
    @Test
    public void testSelectDemo1(){
        List<User> list = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
        System.out.println(list);
        // 因为数据库中只有id = 1的记录,所以只返回一条记录 
    }
  6. 分页查询(用的多)
    • 配置分页插件
      @Configuration
      @MapperScan("com.atguigu.mpdemo1010.mapper")   
      public class MpConfig {
          // 配置分页插件
          @Bean
          public MybatisPlusInterceptor page() {
              MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
              interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
              return interceptor;
          }
      }
    • 编写分页代码
      @Test
      void testPage()
          // 1.创建page对象
          // 传入两个参数:当前页和每页显示记录数
          Page<User> page = new Page<>(1,3);
          // 2.分页查询
          userMapper.selectPage(page,null);
          // 通过page对象获取分页数据
          System.out.println(page.getCurrent());  // 当前页  1
          System.out.println(page.getRecords());  // 每页数据的list集合
          System.out.println(page.getSize());     // 每页显示的记录数     3
          System.out.println(page.getTotal());    // 总记录数     8
          System.out.println(page.getPages());    // 一共有多少页   3
          System.out.println(page.hasNext());     // 是否有下一页   true
          System.out.println(page.hasPrevious()); // 是否有上一页   false
      }
  7. 物理删除、逻辑删除
    • 物理删除:从硬盘中删除数据,删掉就真的从数据库里消失了
      // 物理删除
      @Test
      public void testDeleteById()
          // 根据id查询数据
          User user = userMapper.selectById(1461239461974220809l);
          int res = userMapper.deleteById(1461239461974220809l);
          System.out.println(res);
      }
    • 逻辑删除:数据库中的字段 deleted表示是否删除(删除之后记录还存在于数据库中,但是deleted字段变为1)
      // 1.在数据库表中添加逻辑删除的字段,对应实体类添加属性
      @TableLogic
      private Integer delete;
      # 2.在实体类上加注解
      mybatis-plus.global-config.db-config.logic-delete-value=1
      mybatis-plus.global-config.db-config.logic-not-delete-value=0
      // 3.测试
      @Test
      void testDeleteBatchIds()
          int res = userMapper.deleteBatchIds(Arrays.asList(2,3,4));
          System.out.println(res);
      }
    • 测试结果
  8. 复杂条件查询
    // MybatisPlus实现复杂条件查询
    @Test
    void testSelectQuery()
        // 创建QueryWrapper对象
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // 通过QueryWrapper设置条件
        // ge/gt/le/lt
        // 查询age >= 30的记录
        wrapper.ge("age",30);
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
        // eq/ne
        wrapper.eq("name","Lucy");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
        // between
        // 年龄在20-30范围
        wrapper.between("age",20,30);
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
        // like
        wrapper.like("name","n");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
        // orderByDesc
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
        // last
        wrapper.last("limit 3");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
        // 指定要查询的列
        wrapper.select("id","name");
        List<User> users = userMapper.selectList(wrapper);
        System.out.println(users);
    }
  9. 自动填充
    • 在相关实体上添加注解
      @TableField(fill = FieldFill.INSERT)
      private Date createTime;
      @TableField(fill = FieldFill.INSERT_UPDATE)
      private Date updateTime;
    • 配置handler
      @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);
          }
          // 使用mp实现修改操作,该方法会执行
          @Override
          public void updateFill(MetaObject metaObject) {
              this.setFieldValByName("updateTime",new Date(),metaObject);
          }
      }

文章作者: Prannt
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Prannt !
评论
  目录