mybatis-plus 思维导图,让 mybatis-plus 不再难懂

mybatis-plus 与 mybatis

mybatis

Mybatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects, 普通的 Java 对象) 映射成数据库中的记录。

null

回顾 mybatis 的特点.png

但 mybatis 有个让我比较头疼的一个问题是 sql 工作量很大,尤其是字段多的时候。虽然说单表的增删改查操作可以通过 mybatis generator 工具来生成(或者自己写模板工具生成),但项目开发的过程中总免不了要新添加新字段,这些工具就帮不了我了,我得把新字段写到原来的所有增删改查的 sql 中。这是个痛苦的过程,特别是当你重复了很多次之后。

mybatis 的单表操作也是贼麻烦的事,因为筛选的条件可能会各种各样,所以你不得不写很多动态 sql 来兼容查询条件,这也让我不能集中精力去处理业务。

每当这时候,我怀念 Hibernate 了。嘿嘿,Hibernate 加字段就贼简单,单表操作也是贼方便。但我依然不喜欢用 Hibernate,哈哈。

mybatis-plus

而 mybatis-plus 这样一个框架,一种集 mybatis 与 hibernate 的优点一起的框架。它提供了 hibernate 的单表 CRUD 操作的方便同时,又保留了 mybatis 的特性。

先来看看官方怎么解释 mybatis-plus 的:

  • Mybatis-Plus(简称 MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

null

Mybatis-Plus 与 Mybatis.png

  • 我们的愿景是成为Mybatis最好的搭档,就像 Contra Game 中的 1P、2P,基友搭配,效率翻倍。

null

Contra Game 的 1P、2P.png

带问题去学习,请思考

  • mybatis-plus 怎么实现单表 URUD 操作?
  • mybatis-plus 的底层实现原理是什么?
  • mybatis-plus 与其他同类框架如 mybatis helper 有很什么优势?
  • 如何集成 mybatis-plus 快速搭建一个 spring boot 项目。

特性

null

image.png

从上图可以看出,mybatis-plus 不仅仅封装了基本的 CRUD 操作,还内置了防 SQL 注入操作、常用的分页插件,还有我最喜欢的 ActiveRecord 模式。

用过 jfinal 的人应该都知道 ActiveRecord 是啥。Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象 Object 到关系数据库的映射。

常用实体注解

MP 通过 ORM 模式封装了常用的 CRUD 操作,自然少不了实体注解,先来看看都有哪些注解

null

MP 常用实体注解.png

其中实体无注解化设置可以如下处理:

  • 当数据库的表字段名是驼峰命名时无需注解处理。
  • 或者全局配置: 下划线命名 dbColumnUnderline 设置 true , 大写 isCapitalMode 设置 true

但其实我压根就没管过手写过这些注解,使用 mp 代码生成器自动生成主体后直接覆盖原来的就行了,减少人工的失误,方便快捷。至于 @Version 与 @KeySequence 这两个注解,貌似我还真没用过。嘿嘿。。。

简化 CRUD

前面已经说了 mp 已经简化了 mybatis 的单表基本操作,先来看看。

null

MP 增删改查.png

相比两种写法,我更喜欢 ActiveRecord 的模式写法,因为我不用注入 userMapper,new 了一个对象之后直接调用方法操作就行了。

复杂的查询也很简单,新建一个 EntityWrapper 作为查询对象,Wrapper 接口封装了很多常用的方法。几乎 sql 能写出来的条件调用 Wrapper 的方法就能表现出来。

null

筛选条件 Wrapper 的方法.png

架构原理

参考答案略。

不过我建议你去 mp 官网或者这里看看,哈哈 -> mybatis-plus 实践及架构原理.pdf

mybatis plus 代码生成器 与 mybatis generator

说起 mybatis plus 代码生成器的代码,我记得以前这这篇文章中介绍过

现在再拿来用下哈。原理其实很简单,定义好 velocity 模板(当然你也可以自定义),然后传参数渲染模板生成对应的文件。

我建议你生成的位置最好不要直接覆盖原来的文件,你可能已经有过修改,直接覆盖的话会导致丢失。

null

mp 代码生成器原理.png

而 mybatis generator 生成的代码就是基本的增删改查和实体。模板好像改不了,灵活性明显不够。

mp 插件拓展

mp 不仅仅帮我们实现了基本的增删改查操作,同时还扩展了很多实用的插件。让开发的过程更加简单。

null

插件拓展.png

分页插件

按如下步骤:

  • 自定义查询语句分页(自己写 sql/mapper)
  • spring 注入 mybatis 配置分页插件
<plugins>
    <!--
     | 分页插件配置
     | 插件提供二种方言选择:1、默认方言 2、自定义方言实现类,两者均未配置则抛出异常!
     | overflowCurrent 溢出总页数,设置第一页 默认false
     | optimizeType Count优化方式 ( 版本 2.0.9 改为使用 jsqlparser 不需要配置 )
     | -->
    <!-- 注意!! 如果要支持二级缓存分页使用类 CachePaginationInterceptor 默认、建议如下!! -->
    <plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor">
        <property name="sqlParser" ref="自定义解析类、可以没有" />
        <property name="localPage" value="默认 false 改为 true 开启了 pageHeper 支持、可以没有" />
        <property name="dialectClazz" value="自定义方言类、可以没有" />
    </plugin>
</plugins> 
//Spring boot方式
@EnableTransactionManagement
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
} 
  • UserMapper.java 方法内容
public interface UserMapper{//可以继承或者不继承BaseMapper
    /**
     * <p>
     * 查询 : 根据state状态查询用户列表,分页显示
     * </p>
     *
     * @param page
     *            翻页对象,可以作为 xml 参数直接使用,传递参数 Page 即自动分页
     * @param state
     *            状态
     * @return
     */
    List<User> selectUserList(Pagination page, Integer state);
} 
  • UserServiceImpl.java 调用翻页方法,需要 page.setRecords 回传给页面
public Page<User> selectUserPage(Page<User> page, Integer state) {
    return page.setRecords(userMapper.selectUserList(page, state));
} 
  • UserMapper.xml 等同于编写一个普通 list 查询,mybatis-plus 自动替你分页
<select id="selectUserList" resultType="User">
    SELECT * FROM user WHERE state=#{state}
</select> 
逻辑删除插件

逻辑删除的效果 ---> 会在 mp 自带查询和更新方法的 sql 后面,追加『逻辑删除字段』=『LogicNotDeleteValue 默认值』 删除方法: deleteById() 和其他 delete 方法, 底层 SQL 调用的是 update tbl_xxx set 『逻辑删除字段』=『logicDeleteValue 默认值』

配置如下:

  1. 修改 集成 全局注入器为 LogicSqlInjector
@Bean
public GlobalConfiguration globalConfiguration() {
    GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());
    conf.setLogicDeleteValue("-1");
    conf.setLogicNotDeleteValue("1");
    conf.setIdType(2);
    return conf;
} 
  1. application.yml 全局注入值:
    logicDeleteValue // 逻辑删除全局值
    logicNotDeleteValue // 逻辑未删除全局值
mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.baomidou.springboot.entity
  typeEnumsPackage: com.baomidou.springboot.entity.enums
  global-config:
    #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
    id-type: 2
    #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
    field-strategy: 2
    db-column-underline: true
    #逻辑删除配置
    logic-delete-value: 0
    logic-not-delete-value: 1
    sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector 
  1. 逻辑删除的字段需要注解 @TableLogic
@TableName("tbl_user")
public class UserLogicDelete {

    private Long id;
    ...

    @TableField(value = "delete_flag")
    @TableLogic
    private Integer deleteFlag;
} 

spring 整合 mybatis-plus 的优秀案例