1、deleteAll和UpdateAllColumnById方法执行全局表达式
public enum FactorySqlMethod {
/**
* 删除全部
*/
DELETE_ALL("deleteAll", "根据 entity 条件删除记录", "<script>\nDELETE FROM %s %s\n</script>"),
/**
* 根据id修改数据
*/
UPDATE_ALL_COLUMN_BY_ID("updateAllColumnById", "根据ID 选择修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>");
private final String method;
private final String desc;
private final String sql;
FactorySqlMethod(String method, String desc, String sql) {
this.method = method;
this.desc = desc;
this.sql = sql;
}
public String getMethod() {
return method;
}
public String getDesc() {
return desc;
}
public String getSql() {
return sql;
}
}
2、重新定义UpdateAllColumnById方法执行类以及deleteAll方法执行类
UpdateAllColumnById
public class UpdateAllColumnById extends AbstractMethod {
private static Logger log = LoggerFactory.getLogger(UpdateAllColumnById.class);
@Override
public MappedStatement injectMappedStatement(final Class<?> mapperClass, final Class<?> modelClass, final TableInfo tableInfo) {
FactorySqlMethod sqlMethod = FactorySqlMethod.UPDATE_ALL_COLUMN_BY_ID;
//如果配置了@Version和逻辑删除,additional会变成条件:<if test="et != null and et['version'] != null"> AND version=#{MP_OPTLOCK_VERSION_ORIGINAL}</if> AND del_flag=0
//String additional = this.optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true);
// 反射修改fieldFill值为update
final List<TableFieldInfo> fieldList = tableInfo.getFieldList();
for (final TableFieldInfo tableFieldInfo : fieldList) {
final Class<? extends TableFieldInfo> aClass = tableFieldInfo.getClass();
try {
final Field fieldFill = aClass.getDeclaredField("fieldFill");
fieldFill.setAccessible(true);
fieldFill.set(tableFieldInfo, FieldFill.UPDATE);
}
catch (final NoSuchFieldException e) {
log.error("获取fieldFill失败", e);
}
catch (final IllegalAccessException e) {
log.error("设置fieldFill失败", e);
}
}
final String sql = String.format(sqlMethod.getSql(),
tableInfo.getTableName(),
InjectorSqlSet.sqlSet(false, false, tableInfo, Constants.ENTITY_DOT),
tableInfo.getKeyColumn(),
Constants.ENTITY_DOT + tableInfo.getKeyProperty(),
new StringBuilder("<if test=\"et instanceof java.util.Map\">")
.append("<if test=\"et.MP_OPTLOCK_VERSION_ORIGINAL!=null\">")
.append(" AND ${et.MP_OPTLOCK_VERSION_COLUMN}=#{et.MP_OPTLOCK_VERSION_ORIGINAL}")
.append("</if></if>"));
final SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
}
}
deleteAll
public class DeleteAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql;
FactorySqlMethod mySqlMethod = FactorySqlMethod.DELETE_ALL;
if (tableInfo.isLogicDelete()) {
sql = String.format(mySqlMethod.getSql(), tableInfo.getTableName(), tableInfo,
sqlWhereEntityWrapper(true,tableInfo));
} else {
mySqlMethod = FactorySqlMethod.DELETE_ALL;
sql = String.format(mySqlMethod.getSql(), tableInfo.getTableName(),
sqlWhereEntityWrapper(true,tableInfo));
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addDeleteMappedStatement(mapperClass, mySqlMethod.getMethod(), sqlSource);
}
}
3、编写生成sql的公共方法
public class InjectorSqlSet {
public static String sqlSet(boolean logic, boolean ew, TableInfo table, String prefix) {
String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
String sqlScript = table.getFieldList().stream()
.filter(i -> {
if (logic) {
return !(table.isWithLogicDelete() && i.isLogicDelete());
}
return true;
})
.map(i -> {
return getSqlSet(i, newPrefix);
}).collect(Collectors.joining(StringPool.NEWLINE));
if (ew) {
sqlScript += StringPool.NEWLINE;
sqlScript += SqlScriptUtils.convertIf(SqlScriptUtils.unSafeParam(Constants.U_WRAPPER_SQL_SET),
String.format("%s != null and %s != null", Constants.WRAPPER, Constants.U_WRAPPER_SQL_SET), false);
}
sqlScript = SqlScriptUtils.convertTrim(sqlScript, "SET", null, null, ",");
return sqlScript;
}
private static String getSqlSet(TableFieldInfo i, String prefix) {
String newPrefix = prefix == null ? StringPool.EMPTY : prefix;
String column = i.getColumn();
String update = i.getUpdate();
FieldFill fieldFill = i.getFieldFill();
String el = i.getEl();
// 默认: column=
String sqlSet = column + StringPool.EQUALS;
if (StringUtils.isNotEmpty(update)) {
sqlSet += String.format(update, column);
} else {
sqlSet += SqlScriptUtils.safeParam(newPrefix + el);
}
sqlSet += StringPool.COMMA;
if (fieldFill == FieldFill.UPDATE || fieldFill == FieldFill.INSERT_UPDATE) {
// 不进行 if 包裹
return sqlSet;
}
return sqlSet;
}
}
4、重写自己的SqlInjector,记得要将原来的公共方法都引入,方便后续的引用
public class FactorySqlInjector extends AbstractSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
return Stream.of(
new DeleteAll(),
new LogicDeleteByIdWithFill(),
new UpdateAllColumnById(),
new Insert(),
new Delete(),
new DeleteByMap(),
new DeleteById(),
new DeleteBatchByIds(),
new Update(),
new UpdateById(),
new SelectById(),
new SelectBatchByIds(),
new SelectByMap(),
new SelectOne(),
new SelectCount(),
new SelectMaps(),
new SelectMapsPage(),
new SelectObjs(),
new SelectList(),
new SelectPage()
).collect(Collectors.toList());
}
}
5、编写公共的mapper,需要集成原有的baseMapper
public interface FactoryMapper<T> extends BaseMapper<T> {
int deleteAll();
int updateAllColumnById(@Param(Constants.ENTITY) T entity);
}
6、配置自定义SqlInjector,参考mybatisPlus官方网站
spring
<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<!-- 定义MybatisPlus的全局策略配置-->
<bean id ="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<bean id="mySqlInjector" class="com.test.mp.injector.FactorySqlInjector"/>
</bean>
</bean>
springBoot
@Bean
public ISqlInjector sqlInjector() {
return new FactorySqlInjector();
}
7、使用
public interface UserMapper extends FactoryMapper<User> {
List<User> queryUserList();
}