MyBatis-Plus

1,260 阅读5分钟

官网文档
MyBatis-Plus (baomidou.com)

依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

配置文件

使用配置 | MyBatis-Plus
常用配置

mybatis-plus:
  #xml扫描,多个目录用逗号或者分号分割(告诉 Mapper 所对应的 XML 文件位置),classpath*: 中*不能省 ,后面不加/resources, 这两点和mybatis不同
  mapper-locations: classpath*:/mapper/xml/*.xml
  #MyBatis 别名包扫描路径,通过该属性可以给包中的类注册别名,实现类名简写,避免写路径,多个路径用逗号分割
  type-aliases-package: com.wongoing.sys.model
  configuration:
    # 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射
    map-underscore-to-camel-case: true
    #如果查询结果中包含空值的列,则 MyBatis 在映射的时候,会不会映射这个字段
    call-setters-on-nulls: true   #允许在resultType="map"时映射null值
    #这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      #表前缀
      table-prefix: signff_
      #id类型: 0  # 0:数据库ID自增   1:用户输入id  2:全局唯一id(IdWorker)  3:全局唯一ID(uuid)
      id-type: auto

比较完整的配置

mybatis-plus:
  #外部化xml配置
  config-location: classpath:mybatis-config.xml
  #指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
  configuration-properties: classpath:mybatis/config/properties
  #xml扫描,多个目录用逗号或者分号分割(告诉 Mapper 所对应的 XML 文件位置)
  mapper-locations: classpath*:com/wongoing/sys/mapper/xml/*.xml
  #MyBatis 别名包扫描路径,通过该属性可以给包中的类注册别名,多个路径用逗号分割
  type-aliases-package: com.wongoing.sys.model
  #如果配置了该属性,则仅仅会扫描路径下以该类作为父类的域对象
  type-aliases-super-type: java.lang.Object
  #枚举类 扫描路径,如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性
  type-enums-package: com.wongoing.sys.model
  #项目启动会检查xml配置存在(只在开发时打开)
  check-config-location: true
  #SIMPLE:该执行器类型不做特殊的事情,为每个语句的执行创建一个新的预处理语句,REUSE:改执行器类会复用预处理语句,BATCH:该执行器类型会批量执行所有的更新语句
  default-executor-type: REUSE
  configuration:
    # 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射,
    #如selelct时涉及该配置,数据库中下划线命名映射为驼峰命名
    map-underscore-to-camel-case: true
    # 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true
    cache-enabled: true
    #懒加载
    aggressive-lazy-loading: true
    #none:不启用自动映射 partial:只对非嵌套的 resultMap 进行自动映射 full:对所有的 resultMap 都进行自动映射
    auto-mapping-behavior: partial
    #none:不做任何处理 (默认值)warning:以日志的形式打印相关警告信息 failing:当作映射失败处理,并抛出异常和详细信息
    auto-mapping-unknown-column-behavior: none
    #如果查询结果中包含空值的列,则 MyBatis 在映射的时候,会不会映射这个字段
    call-setters-on-nulls: true   #允许在resultType="map"时映射null值
    #这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #是否允许映射结果为多个数据集
    multiple-result-sets-enabled: false
  global-config:
    db-config:
      #表前缀
      table-prefix: signff_
      #表名下划线命名,将驼峰命名的属性名、类名转为下滑线命名,即从经典 Java 属性名 aColumn(驼峰命名)到经典数据库列名 A_COLUMN(下划线命名)的类似映射,
      #如insert时涉及该配置,类中驼峰命名转为下划线命,http://blog.java1234.com/blog/articles/748.html
      table-underline: false
      #id类型: 0  # 0:数据库ID自增   1:用户输入id  2:全局唯一id(IdWorker)  3:全局唯一ID(uuid)
      id-type: auto
      #是否开启大写命名,默认不开启
      capital-mode: false
      #逻辑已删除值,(逻辑删除下有效) 需要注入逻辑策略LogicSqlInjector 以@Bean方式注入
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
      #逻辑未删除值,(逻辑删除下有效)
      logic-delete-value: 1

组件配置示例

大佬文章
SpringBoot集成Mybatis-Plus - 云+社区 - 腾讯云 (tencent.com)

@Configuration
// 指定要扫描的Mapper类的包的路径
@MapperScan("${mybatis-plus.mapperPackage}")
public class MybatisPlusConfig {

   @Bean
   public MybatisPlusInterceptor mybatisPlusInterceptor() {
      MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      // 分页插件
      interceptor.addInnerInterceptor(paginationInnerInterceptor());
      // 乐观锁插件
      interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
      // 阻断插件
      interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
      return interceptor;
   }

   /**
    * 分页插件,默认自动识别数据库类型
    */
   public PaginationInnerInterceptor paginationInnerInterceptor() {
      PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
      // 设置数据库类型为mysql,官方建议使用单一数据库时配置此项。
      paginationInnerInterceptor.setDbType(DbType.MYSQL);
      // 设置最大单页限制数量,默认 500 条,-1 不受限制
      paginationInnerInterceptor.setMaxLimit(-1L);
      return paginationInnerInterceptor;
   }

   /**
    * 乐观锁插件
    */
   public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
      return new OptimisticLockerInnerInterceptor();
   }

   /**
    * 如果是对全表的删除或更新操作,就会终止该操作
    */
   public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
      return new BlockAttackInnerInterceptor();
   }

   /**
    * sql性能规范插件(垃圾SQL拦截)
    * 如有需要可以启用
    */
   public IllegalSQLInnerInterceptor illegalSQLInnerInterceptor() {
      return new IllegalSQLInnerInterceptor();
   }


   /**
    * 自定义主键策略
    * 默认maven可能找不到这个依赖
    */
   @Bean
   public IdentifierGenerator idGenerator() {
      return new CustomIdGenerator();
   }


   /**
    * sql注入器配置,不常用,下面是工作室学长配的,没试过
    */
   @Bean
   public ISqlInjector sqlInjector() {
      return new DefaultSqlInjector() {
         @Override
         public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
            List<AbstractMethod> methodList = super.getMethodList(mapperClass);
            methodList.add(new InsertAll());
            return methodList;
         }
      };
   }
}

自动填充示例


import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;
import java.util.Date;


@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

   @Override
   public void insertFill(MetaObject metaObject) {
      //根据属性名字设置要填充的值
      //方式一
      if (metaObject.hasGetter("createTime")) {
         if (metaObject.getValue("createTime") == null) {
            this.setFieldValByName("createTime", new Date(), metaObject);
         }
      }
      if (metaObject.hasGetter("createUserId")) {
         if (metaObject.getValue("createUserId") == null) {
            this.setFieldValByName("createUserId", "default", metaObject);
         }
      }
      
      //方式二
      this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
      // 或者
      this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
      // 或者
      this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
   }

   @Override
   public void updateFill(MetaObject metaObject) {
      //方式一
      if (metaObject.hasGetter("updateTime")) {
         if (metaObject.getValue("updateTime") == null) {
            this.setFieldValByName("updateTime", new Date(), metaObject);
         }
      }
      if (metaObject.hasGetter("createUserId")) {
         if (metaObject.getValue("createUserId") == null) {
            this.setFieldValByName("createUserId", "default", metaObject);
         }
      }

      //方式二
      this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
      // 或者
      this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
      // 或者
      this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
   }
}

相关问题

条件构造表达式内部条件构造 即使条件为false,后面依然会被执行一次

mapper.(实例a!=null,列b,实例a.method)

即使a==null,实例a.method仍然会被执行,并报空指针异常