1、mybatis查数据库,可以看到 id 是一串相当长的数字,这是什么意思呢?提前剧透一下,这其实是分布式 id,那又何为分布式 id 呢?

分布式 id 的解决方案有很多:UUID,SnowFlake,TinyID,Uidgenerator,Leaf,Tinyid

以 UUID 为例,它生成的是一串由数字和字母组成的字符串,显然并不适合作为数据表的 id,而且 id 保持递增有序会加快表的查询效率,基于此,MyBatisPlus 使用的就是 SnowFlake(雪花算法)。
 
2、我们可以在实体类中使用@TableId(type = IdType.AUTO) // 设置主键策略
来设置主键的策略:

 

这里多说一点, 当实体类的主键名为 id,并且数据表的主键名也为 id 时,此时 MyBatisPlus 会自动判定该属性为主键 id,倘若名字不是 id 时,就需要标注 @TableId 注解,若是实体类中主键名与数据表的主键名不一致,则可以进行声明:
 
3、属性自动填充
数据库插入或更新时自动维护时间属性注解如下-》然后编写一个类实现 MetaObjectHandler 接口:
    @TableField(fill = FieldFill.INSERT) // 插入的时候自动填充
    private LocalDateTime gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新的时候自动填充
    private LocalDateTime gmtModified;
属性填充其实可以进行一些优化,考虑一些特殊情况,对于一些不存在的属性,就不需要进行属性填充,对于一些设置了值的属性,也不需要进行属性填充,这样可以提高程序的整体运行效率:
 
4、逻辑删除

4.1 逻辑删除对应的是物理删除,分别介绍一下这两个概念:

  1. 物理删除 :指的是真正的删除,即:当执行删除操作时,将数据表中的数据进行删除,之后将无法再查询到该数据
  2. 逻辑删除 :并不是真正意义上的删除,只是对于用户不可见了,它仍然存在与数据表中
  /**
     * 逻辑删除属性
     */
    @TableLogic
    @TableField("is_deleted")
    private Boolean deleted;
还是参照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议,对于布尔类型变量,不能加 is 前缀,所以我们的属性被命名为 deleted,但此时就无法与数据表的字段进行对应了,
所以我们需要使用 @TableField 注解来声明一下数据表的字段名,而 @TableLogin 注解用于设置逻辑删除属性;此时我们执行删除操作:
 

4.2 增加了如上注解后,查询时携带了一个条件: is_deleted=0 ,这也说明了 MyBatisPlus 默认 0 为不删除,1 为删除。 若是你想修改这个规定,比如设置-1 为删除,1 为不删除,也可以进行配置,

如下是全局配置,也可以单独一个表一个属性进行配置如mybatisplus逻辑删除基本实现和坑点解决_java_脚本之家 (jb51.net)

mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      logic-delete-field: deleted # 逻辑删除属性名
      logic-delete-value: -1 # 删除值
      logic-not-delete-value: 1 # 不删除值
 
 

4.3 我们可以输出 MyBatisPlus 生成的 SQL 来分析一下,在配置文件中进行配置:

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出SQL日志
 
分页插件
注册分页插件(和下面乐观锁插件在同一个地方注册)-》service使用分页插件提供的功能
 
乐观锁插件
然后注册乐观锁插件-》MyBatisPlus 已经提供了乐观锁机制,只需要在实体类中使用 @Version 声明版本号属性:
@Configuration
public class MyBatisConfig {
    /**
     * 注册插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
 
条件构造器
在分页插件中我们简单地使用了一下条件构造器(Wrapper),下面我们来详细了解一下。 先来看看 Wrapper 的继承体系:

 

  • Wrapper:条件构造器抽象类,最顶端的父类
    • AbstractWrapper:查询条件封装抽象类,生成 SQL 的 where 条件
      • QueryWrapper:用于对象封装
      • UpdateWrapper:用于条件封装
    • AbstractLambdaWrapper:Lambda 语法使用 Wrapper
      • LambdaQueryWrapper:用于对象封装,使用 Lambda 语法
      • LambdaUpdateWrapper:用于条件封装,使用 Lambda 语法

通常我们使用的都是 QueryWrapper 和 UpdateWrapper,如下

@SpringBootTest

@MapperScan("com.wwj.mybatisplusdemo.mapper")

class MybatisplusDemoApplicationTests {

    @Autowired

    private EmployeeMapper employeeMapper;

    @Test

    void contextLoads() {

        // 查询名字中包含'j',年龄大于20岁,邮箱不为空的员工信息

        QueryWrapper<Employee> wrapper = new QueryWrapper<>();

        wrapper.like("last_name", "j");  // like可以看到它是对 j 的前后都加上了 % ,若是只想查询以 j 开头的名字,则可以使用 likeRight 方法,若是想查询以 j 结尾的名字,,则使用 likeLeft 方法。

        wrapper.gt("age", 20);

        wrapper.isNotNull("email");

        List<Employee> list = employeeMapper.selectList(wrapper);

        list.forEach(System.out::println);

    }

}