1、插件
在 MyBatis 中,允许在已映射语句执行过程中的某一点进行拦截调用。而 Mybatis-plus 中的插件就是根据 MyBatis 的拦截器实现的。 Mybatis-plus 中提供的插件:
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
下面我主要了解一下自动分页和乐观锁这两个插件。
1.1、分页插件
分页插件在之前讲解 BaseMapper 类时就已经使用过了,这里主要了解分页插件的配置:
<!-- spring xml 方式 -->
<property name="plugins">
<array>
<bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
<property name="sqlParser" ref="自定义解析类、可以没有"/>
<property name="dialectClazz" value="自定义方言类、可以没有"/>
<!-- COUNT SQL 解析.可以没有 -->
<property name="countSqlParser" ref="countSqlParser"/>
</bean>
</array>
</property>
<bean id="countSqlParser" class="com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize">
<!-- 设置为 true 可以优化部分 left join 的sql -->
<property name="optimizeJoin" value="true"/>
</bean>
//Spring boot方式
//在 Spring boot启动类中添加
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
1.2、乐观锁
乐观锁 这个插件的作用是:当要更新一条记录的时候,希望这条记录没有被别人更新,这个插件需要跟@Version
注解一起配合使用,且使用时不需要主动调用。
- 配置乐观锁
<!-- spring xml方式: --> <bean class="com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor" id="optimisticLockerInnerInterceptor"/> <bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor"> <property name="interceptors"> <list> <ref bean="optimisticLockerInnerInterceptor"/> </list> </property> </bean>
//Spring boot方式 //在 Spring boot启动类中添加 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }
- 在实体类的字段上添加注解:支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
@Version private XXX XXX;
2、Sql 注入器
在 Mybatis-plus 中,通过 AbstractSqlInjector 类将 BaseMapper 中的方法注入到了 Mybatis 容器,这样这些方法就可以正常执行。
而有些时候 Mybatis-plus 中的这些方法可能不够用,所以Mybatis-plus 就提供了 Sql 注入器扩充BaseMapper中的方法。
- 创建一个类继承 BaseMapper 类:这个类用于继承 BaseMapper 类之前的方法,然后定义所需要的扩充方法。
public interface MyBaseMapper<T> extends BaseMapper<T> { List<T> findAll(); }
- 创建一个类继承 DefaultSqlInjector 类:这个类用于将扩充的方法注入到了 Mybatis 容器中,
DefaultSqlInjector
类是AbstractSqlInjector
的子类。public class MySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList() { //固定语句 List<AbstractMethod> methodList = super.getMethodList(); //将再扩充自定义的方法 methodList.add(new FindAll()); return methodList; } }
- 创建一个类继承 AbstractMethod 类:这个类用于实现扩充的方法。
public class FindAll extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { //这个参数有你的扩展方法名相同,且必须相同 String sqlMethod = "findAll"; //这个就是根据参数编写具体的SQL语句 String sql = "select * from " + tableInfo.getTableName(); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo); } }
- 将定义的方法注册到 Spring 容器中:在启动类中添加如下代码
/*** 自定义SQL注入器 */ @Bean public MySqlInjector mySqlInjector(){ return new MySqlInjector(); }
- 修改 Mapper 文件 :想要使用扩展的方法,Mapper 接口必须继承自定义的 BaseMapper 类。
public interface UserMapper extends MyBaseMapper<User> {}
3、自动填充功能
在插入或者更新数据时,希望有些字段可以自动填充数据,例如数据创建时间、数据最后一次修改时间等。在 Mybatis-plus 中提供了这样的功能,可以实现自动填充。
- 创建一个自动填充类:这个类实现 MetaObjectHandler 接口。
@Component public class MyMetaObjectHandler implements MetaObjectHandler { //在添加数据时自动填充处理某个字段 @Override public void insertFill(MetaObject metaObject) { //得到实体类中某些属性的属性值,可以获取多个属性值 Object object=getFieldValByName("属性值", metaObject); //可以先对某个属性值进行判断,然后再选择进行设置 if(object == null){ //设置实体类中某些属性的属性值,可以设置多个属性值 setFieldValByName("password", "123456", metaObject); } } //在修改数据时自动填充处理某个字段 @Override public void updateFill(MetaObject metaObject) { //同 insertFill 方法 } }
- 指定使用自动填充的属性:在实体类中,通过
@TableField
注解让某些字段进行自动填充操作。//截取的实体类的一部分 //FieldFill 是一个枚举,用于表示在什么操作是使用自动填充 //当前表示在插入和修改时都进行自动填充 @TableField(fill = FieldFill.INSERT_UPDATE) private String date;
//FieldFill是一个枚举 public enum FieldFill { /*** 默认不处理 */ DEFAULT, /*** 插入时填充字段 */ INSERT, /*** 更新时填充字段 */ UPDATE, /*** 插入和更新时填充字段 */ INSERT_UPDATE }
4、逻辑删除
逻辑删除指将数据标记为删除,而并非真正的物理删除(非DELETE操作)
。在查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免数据被真正的删除。
- 修改数据库表结构:因为需要将数据标记为删除,所以需要一个字段用于标记。
ALTER TABLE `XXX` ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER `version`;
- 修改实体类:使用``注解,将某一个字段标记为逻辑删除
//截取的实体类的一部分 @TableLogic private String deleted;
- 进行配置:
mybatis-plus: global-config: db-config: logic-delete-field: flag # 全局逻辑删除的实体字段名(配置后可以忽略不配置修改实体类) logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)