插件扩展
1. Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求完成相关数据的动态改变
- Executor
- StatementHandler
- ParameterHandler
- ResultSetHandler
2. MP从3.4.0版本开始,提供的插件都将基于InnerInterceptor接口来实现功能
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
3. 对sql进行单次改造的优先放入,不对sql进行改造的最后放入,建议使用顺序
- 多租户,动态表名
- 分页,乐观锁
- sql性能规范,防止全表更新与删除
自定义SQL
1. 自定义方法的配置类继承DefaultSqlInjector
- DefaultSqlInjector继承了抽象类 AbstractSqlInjector
- AbstractSqlInjector实现了ISqlInjector接口
public class MyLogicSqlInjector extends DefaultSqlInjector {
/**
* 如果只需增加方法,保留MP自带方法
* 可以super.getMethodList() 再add
* @return
*/
@Override
public List<AbstractMethod> getMethodList(
Class<?> mapperClass,
TableInfo tableInfo) {
List<AbstractMethod> methodList =
super.getMethodList(mapperClass, tableInfo);
methodList.add(new MyInsertAll());
return methodList;
}
}
2. 自定义方法继承AbstractMethod抽象类
- 在版本2.3中自定义方法是继承AutoSqlInjector类(实现ISqlInjector接口),重写inject()方法
public class MyInsertAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(
Class<?> mapperClass,
Class<?> modelClass,
TableInfo tableInfo) {
//注入的SQL语句
String sql = "insert into %s %s values %s";
//表字段名
StringBuilder fieldSql = new StringBuilder();
fieldSql.append(tableInfo.getKeyColumn()).append(",");
//字段占位符#{}
StringBuilder valueSql = new StringBuilder();
valueSql.append("#{").append(tableInfo.getKeyProperty()).append("},");
tableInfo.getFieldList().forEach(x->{
fieldSql.append(x.getColumn()).append(",");
valueSql.append("#{").append(x.getProperty()).append("},");
});
fieldSql.delete(fieldSql.length()-1, fieldSql.length());
fieldSql.insert(0, "(");
fieldSql.append(")");
valueSql.insert(0, "(");
valueSql.delete(valueSql.length()-1, valueSql.length());
valueSql.append(")");
SqlSource sqlSource =
languageDriver.createSqlSource(configuration,
String.format(sql,
tableInfo.getTableName(),
fieldSql.toString(),
valueSql.toString()),
modelClass);
return this.addInsertMappedStatement(
mapperClass, modelClass,
//注入的方法名 一定要与Mapper接口中的方法名一致
"myInsertAll",
sqlSource, new NoKeyGenerator(), null, null);
}
}
3. AbstractMethod类有多个子类可供参考
自动填充
- 实体类字段加上注解@TableField(fill = FieldFill.INSERT)
- 自定义填充处理类实现元对象处理器接口
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(
metaObject, "username", String.class, "Jetty");
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(
metaObject, "username", String.class, "Tom");
}
}
Sequence主键
1. 主键生成策略必须使用INPUT
2. 实体类上使用注解@KeySequence(value = "主键序列名", clazz = 主键属性类.class)
3. 版本3.3.0开始自动识别主键类型
4. 默认版本支持:可以通过实现IKeyGenerator接口来自定义策略
- DB2KeyGenerator
- H2KeyGenerator
- KingbaseKeyGenerator
- OracleKeyGenerator
- PostgreKeyGenerator