Mybatis-mybatis-plus-tkmabatis-表前缀设置-全局Interceptor拦截替换sql表前缀
mybatis-plus相关配置,按需使用
mybatis-plus:
global-config:
db-config:
#tk方法的表前缀
table-prefix: ${spring.application.name}_
configuration-properties:
# 自定义sql中表名带前缀 https://www.cnblogs.com/javalinux/p/14338780.html
# prefix 是内置参数
prefix: ${spring.application.name}_
# key1等是自定义的,使用时直接${key1} ,但是不要使用#
# key1: 2222
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
全局替换sql表前缀
package cn.jiangjiesheng.inp.aspect;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.sql.Connection;
/**
* 自定义 MyBatis 拦截器
*/
// https://blog.csdn.net/weixin_34082854/article/details/86452841
/**
* method:表示拦截的方法,mybatis支持的方法有 update, query, flushStatements, commit, rollback, getTransaction, close, isClosed
* 方法,其中,update包括新增、修改、删除等方法,query用于查询,其它的基本用不到。
* args:表示拦截的参数类型,有MappedStatement、Object、RowBounds和ResultHandler等等.
* type:表示拦截的类,有Executor、StatementHandler、ParameterHandler和ResultSetHandler。
*
*
* 实际使用时要测试 tkmybatis代码直接使用、mapper xml、@Insert注解类的sql的增删改查
*
*/
@Component
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Slf4j
public class MySqlInterceptor implements Interceptor {
private static final Logger logger= LoggerFactory.getLogger(MySqlInterceptor.class);
@Value("${spring.application.name}")
private String springApplicationName;
/**
* intercept 方法用来对拦截的sql进行具体的操作
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
//logger.info("执行intercept方法:{}", invocation.toString());
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String origSql = boundSql.getSql();
//logger.info("原始SQL: {}", origSql);
// 组装新的 sql
//这种需要代码中的默认都是应inp来
if(!origSql.contains("newinp_") && "newinp".equals(springApplicationName)){
String newSql = origSql.replaceAll("inp_",springApplicationName+"_");
//logger.info("改写的SQL: {}", newSql);
Field field = boundSql.getClass().getDeclaredField("sql");
field.setAccessible(true);
field.set(boundSql, newSql);
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
// 这里的实现非常关键,是保证@Intercepts注解、intercept方法能不能进来的判断开关
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}
return target;
}
}
如果sql拦截不生效【重要】
package spcommon.config;
import com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
@Configuration
@AutoConfigureAfter(PageHelperAutoConfiguration.class)
public class MyBatisConfig {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
@PostConstruct
public void addMySqlInterceptor() {
MySqlInterceptor interceptor = new MySqlInterceptor(); //上述示例
MySqlInsertValueInterceptor handleInsertValueInterceptor = new MySqlInsertValueInterceptor(); //实际应用
MySqlSelectResultInterceptor handleSelectResultIInterceptor = new MySqlSelectResultInterceptor();//实际应用
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
// 添加自定义属性
// Properties properties = new Properties();
// properties.setProperty("prop1", "value1");
// interceptor.setProperties(properties);
sqlSessionFactory.getConfiguration().addInterceptor(interceptor);
sqlSessionFactory.getConfiguration().addInterceptor(handleInsertValueInterceptor);
sqlSessionFactory.getConfiguration().addInterceptor(handleSelectResultIInterceptor);
}
}
}
在 resources 目录下创建META-INF目录下,在 META-INF 目录下创建 spring.factories 文件,文件内容如下:
xxx.xxx.MyBatisConfig
实际使用1 去掉mybatis insert sql 中的 空值字段**
package cn.jiangjiesheng.edu.config.datasource;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.logging.log4j.util.Strings;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.persistence.Column;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 自定义 MyBatis 拦截器
*/
// https://blog.csdn.net/weixin_34082854/article/details/86452841
/**
* method:表示拦截的方法,mybatis支持的方法有 update, query, flushStatements, commit, rollback, getTransaction, close, isClosed
* 方法,其中,update包括新增、修改、删除等方法,query用于查询,其它的基本用不到。
* args:表示拦截的参数类型,有MappedStatement、Object、RowBounds和ResultHandler等等.
* type:表示拦截的类,有Executor、StatementHandler、ParameterHandler和ResultSetHandler。
* <p>
* <p>
* 实际使用时要测试 tkmybatis代码直接使用、mapper xml、@Insert注解类的sql的增删改查
*/
@Component
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Slf4j
public class MySqlInsertValueInterceptor implements Interceptor {
@Value("${spring.application.name}")
private String springApplicationName;
private static String INVALID_SYMBOL = "[\r\n\t]";
public static String BLANK = " ";
public static String MORE_BLANK = BLANK + BLANK;
private final static String INSERT_INFO_KEY = "INSERT ";//INTO
private final static String INSERT_INFO_PK_ID = "id";
/**
* intercept 方法用来对拦截的sql进行具体的操作
*
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
//logger.info("执行intercept方法:{}", invocation.toString());
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String origSql = boundSql.getSql().replaceAll(INVALID_SYMBOL, "");
origSql = replaceMoreBlank(origSql);
//logger.info("原始SQL: {}", origSql);
if (origSql.contains(INSERT_INFO_KEY)) {
//为空的字段
Object parameterObject = boundSql.getParameterObject();
if (parameterObject != null) {
//获取到所有的字段
List<String> filedList = Arrays.asList(origSql.substring(origSql.indexOf("(") + 1, origSql.indexOf("VALUES") - 2).replaceAll(" ", "").split(","));
boolean isMap = parameterObject instanceof Map;
if (isMap) {
//批量插入的,就把空字符串的改成两个空格
setEmptyStringToBlankForBatchInsert(parameterObject, filedList);
} else {
//单条插入插入的,就把空字符串的字段都去掉(不适合批量插入的场景)
//TODO 1 关注
// @Column(name = "enterprise_id")
// private String containerId; 对于这种无法判断,所以由于所有的字段都把not null 去掉了 ,但是现有表还有 not null的id,所以值处理id吧。如果不是有id,可能本class类都可以不用了
//要映射成和 @Column(name = "enterprise_id") 字段相同的
//
// @Column(name = "enterprise_id")
// @ApiModelProperty(value = "容器(企业)ID")
// private String containerId;
//需要重写setContainerId,给数据库的实际字段增加一个赋值
// private String enterpriseId;
//
// public void setContainerId(String containerId) {
// this.containerId = containerId;
// this.enterpriseId = containerId;
// }
NotNullFieldListVo notNullFieldListVo = getNotNullFieldList(parameterObject, filedList);
List<String> notNullDatabaseFieldList = notNullFieldListVo.getNotNullDatabaseFiledList();
List<String> notNullEntityField = notNullFieldListVo.getNotNullEntityField();
// List<String> notNullDatabaseFieldList = Lists.newArrayList(filedList);
// notNullDatabaseFieldList.remove(INSERT_INFO_PK_ID);
String newSql = getNoNullInsertSql(origSql, notNullDatabaseFieldList);
Field field = boundSql.getClass().getDeclaredField("sql");
//重要
field.setAccessible(true);
field.set(boundSql, newSql);
int batchCount = newSql.split("\\),\\(").length;
if (batchCount == 1) {
//TODO 1 关注
// @Column(name = "enterprise_id") itemAnalysisPic
// private String containerId; 对于这种无法判断,所以由于所有的字段都把not null 去掉了 ,但是现有表还有 not null的id,所以值处理id吧。如果不是有id,可能本class类都可以不用了
List<String> notNullTufenFieldList = covert2TuofengField4check(notNullDatabaseFieldList);
List<ParameterMapping> getParameterMappings = boundSql.getParameterMappings().stream().
filter(parameterMapping -> {
String property = getProperty(parameterMapping);
return notNullTufenFieldList.contains(property) || notNullEntityField.contains(property);
})
.distinct().collect(Collectors.toList());
Field fieldParameterMappings = boundSql.getClass().getDeclaredField("parameterMappings");
//重要
fieldParameterMappings.setAccessible(true);
fieldParameterMappings.set(boundSql, getParameterMappings);
// List<ParameterMapping> getParameterMappings = boundSql.getParameterMappings().stream().
// filter(y -> !INSERT_INFO_PK_ID.equals(getProperty(y)))
// .distinct().collect(Collectors.toList());
// Field fieldParameterMappings = boundSql.getClass().getDeclaredField("parameterMappings");
// fieldParameterMappings.setAccessible(true);
// fieldParameterMappings.set(boundSql, getParameterMappings);
}
}
}
}
return invocation.proceed();
}
@NotNull
private String getProperty(ParameterMapping y) {
String property = y.getProperty().replaceAll("`", "");
if (property.contains(".")) {
property = property.substring(property.lastIndexOf(".") + 1);
}
return property;
}
@Override
public Object plugin(Object target) {
// 这里的实现非常关键,是保证@Intercepts注解、intercept方法能不能进来的判断开关
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}
return target;
}
private NotNullValueFieldVo isNotNullValueField(Object parameterObject, String databaseFiled) {
Field field = null;
NotNullValueFieldVo vo = new NotNullValueFieldVo();
try {
//带` 这种关键字的不知道怎么办
//
String filed = covert2TuofengField(databaseFiled);
//field = parameterObject.getClass().getDeclaredField(filed.replaceAll("`", ""));
Class cls = null;
boolean isMap = parameterObject instanceof Map;
if (isMap) {
//这里实际不走了 【批量场景】
//这种一般是mapper中自定义sql做的批量插入 所以这种 字段,除了id,其他都认为非空吧,满意真的要空,那在代码中设置值,或者在表结构设上把not null 去掉
if (INSERT_INFO_PK_ID.toLowerCase().equals(filed.toLowerCase())) {
List list = (List) ((MapperMethod.ParamMap) parameterObject).entrySet().toArray()[0];
cls = list.get(0).getClass();
} else {
vo.setIsNotNullValue(true);
vo.setEntityField(filed);
// return true;
return vo;
}
// Object[] objects = ((MapperMethod.ParamMap) parameterObject).entrySet().toArray();
// for (int i = 0; i < objects.length; i++) {
// List ListValue = (List) ((Map.Entry) objects[i]).getValue();
// for (Object o : ListValue) {
// cls = o.getClass();
// field = getFieldIncludeSuper(cls, filed.replaceAll("`", ""), databaseFiled.replaceAll("`", ""));
// field.setAccessible(true);
// Object value = field.get(o);
//
// if (Strings.EMPTY.equals(value)) {
// //TODO oracle,空字符串会认为是null
// field.set(o, BLANK);
// }
// }
//
// }
// List value = (List) ((Map.Entry) objects[0]).getValue();
// List value2 = (List) ((Map.Entry) ((MapperMethod.ParamMap) parameterObject).entrySet().toArray()[1]).getValue();
cls = ((List) ((Map.Entry) ((MapperMethod.ParamMap) parameterObject).entrySet().toArray()[0]).getValue()).get(0).getClass();
} else {
cls = parameterObject.getClass();
}
field = getFieldIncludeSuper(cls, filed.replaceAll("`", ""), databaseFiled.replaceAll("`", ""));
//重要
field.setAccessible(true);
Object value = field.get(parameterObject);
if (Strings.EMPTY.equals(value)) {
//TODO oracle,空字符串会认为是null
field.set(parameterObject, BLANK); //还是也认为是空?
value = BLANK;
}
// return value != null;
vo.setIsNotNullValue(value != null);
vo.setEntityField(field.getName());
return vo;
} catch (Exception e) {
// e.printStackTrace();
}
vo.setIsNotNullValue(false);
vo.setEntityField(null);
return vo;
}
private void setEmptyStringToBlankForBatchInsert(Object parameterObject, List<String> databaseFiledList){
Class cls = null;
Object[] objects = ((MapperMethod.ParamMap) parameterObject).entrySet().toArray();
for (String databaseFiled : databaseFiledList) {
String filed = covert2TuofengField(databaseFiled);
Field field = null;
for (int i = 0; i < objects.length; i++) {
List ListValue = (List) ((Map.Entry) objects[i]).getValue();
for (Object o : ListValue) {
cls = o.getClass();
field = getFieldIncludeSuper(cls, filed.replaceAll("`", ""), databaseFiled.replaceAll("`", ""));
//重要
field.setAccessible(true);
Object value = null;
try {
value = field.get(o);
if (Strings.EMPTY.equals(value)) {
//TODO oracle,空字符串会认为是null
field.set(o, BLANK);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
@Data
private class NotNullValueFieldVo {
private Boolean IsNotNullValue;
private String entityField;
}
@Data
private class NotNullFieldListVo {
private List<String> notNullDatabaseFiledList;
private List<String> notNullEntityField;
}
//反射获取父类中的字段
public static Field getFieldIncludeSuper(Class<?> clazz, String fieldName, String databaseFiled) {
Class<?> clazzBak = clazz;
Field field = null;
while (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException ignore) {
// log.error("获取字段失败:fieldName{},异常:{}", fieldName, ignore);
}
if (field == null) {
clazz = clazz.getSuperclass();
} else {
break;
}
}
if (field == null) {
//还有实体字段和数据库字段不同的
return getFieldIncludeSuperByAnnotation(clazzBak, databaseFiled);
}
return field;
}
/**
* 根据 @Column注解获取到Field字段
*
* @description:
* @author: 江节胜
* @email: dev@jiangjiesheng.cn
*/
public static Field getFieldIncludeSuperByAnnotation(Class<?> clazz, String databaseFiled) {
//https://blog.csdn.net/weixin_30505485/article/details/94817025
Field field = null;
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
for (Field field1 : fields) {
//重要
field1.setAccessible(true);
}
for (Field field1 : fields) {
try {
field = clazz.getDeclaredField(field1.getName());
Column column = field.getAnnotation(Column.class);
if (column != null) {
//System.out.println(column.name());
//System.out.println(column.length());
String name = column.name();
if (StringUtils.isNotBlank(name)) {
if (databaseFiled.equals(column.name().replaceAll("`", ""))) {
return field;
}
}
}
} catch (NoSuchFieldException e) {
}
}
if (field == null) {
clazz = clazz.getSuperclass();
} else {
break;
}
}
return field;
}
private List<String> covert2TuofengField4check(List<String> fieldList) {
List<String> fieldTofengList = Lists.newArrayList();
for (String f : fieldList) {
fieldTofengList.add(covert2TuofengField(f).replaceAll("`", ""));
}
return fieldTofengList;
}
private String covert2TuofengField(String filed) {
if (filed.contains("_")) {
String low = filed.substring(filed.indexOf("_"), filed.indexOf("_") + 2);
String toUper = low.toUpperCase().replaceAll("_", "");
filed = filed.replaceAll(low, toUper);
return covert2TuofengField(filed);
}
return filed;
}
private NotNullFieldListVo getNotNullFieldList(Object parameterObject, List<String> filedList) {
NotNullFieldListVo notNullFieldListVo = new NotNullFieldListVo();
List<String> notNullDatabaseFiledList = Lists.newArrayList();
List<String> notNullEntityFiledList = Lists.newArrayList();
for (String f : filedList) {
NotNullValueFieldVo notNullValueField = isNotNullValueField(parameterObject, f);
if (notNullValueField.getIsNotNullValue()) {
notNullDatabaseFiledList.add(f);
notNullEntityFiledList.add(notNullValueField.getEntityField());
}
}
notNullFieldListVo.setNotNullDatabaseFiledList(notNullDatabaseFiledList.stream().distinct().collect(Collectors.toList()));
notNullFieldListVo.setNotNullEntityField(notNullEntityFiledList.stream().distinct().collect(Collectors.toList()));
return notNullFieldListVo;
}
/**
* @description: 去掉mybatis insertSelective 中的 id,避免某些嵌套的数据库环境,传入报错
* @author: 江节胜
* @email: dev@jiangjiesheng.cn
* @Date 2024-01-26
*/
private String getNoNullInsertSql(String origSql, List<String> notNullFieldList) {
if (origSql.contains(INSERT_INFO_KEY)) {
//INSERT INTO edu_train_category
StringBuilder newSql = new StringBuilder(origSql.substring(0, origSql.indexOf("(") + 1));
newSql.append(StringUtils.join(notNullFieldList, ","));
newSql.append(") VALUES ");
//判断一下有多少插入的条数
String valueSql = origSql.substring(origSql.lastIndexOf("VALUES") + "VALUES".length());
valueSql = replaceBlank(valueSql);
int batchCount = valueSql.split("\\),\\(").length;
for (int i = 0; i < batchCount; i++) {
newSql.append("(");
StringBuilder values = new StringBuilder();
for (String f : notNullFieldList) {
values.append("?,");
}
values = new StringBuilder(values.substring(0, values.length() - 1));
newSql.append(values);
newSql.append(")");
newSql.append(",");
}
newSql = new StringBuilder(newSql.substring(0, newSql.length() - 1));
//去掉id字段 不能用,会把带id,的字段都改了 origSql.replace(INSERT_INFO_PK_ID, Strings.EMPTY);
// String newSql = origSql.substring(0,origSql.indexOf(INSERT_INFO_PK_ID)) + origSql.substring(origSql.indexOf(INSERT_INFO_PK_ID)+INSERT_INFO_PK_ID.length());
// String newSql
//
// 再解析一下 VALUES( ?,?,?,?,?,?,? )
//截止到 VALUES
// String insertSqlPrefix = newSql.substring(0, newSql.lastIndexOf("VALUES") + 6);
// System.out.println(insertSqlPrefix);
// // 带 ()
// String sqlParams = newSql.substring(newSql.lastIndexOf("VALUES") + 6);
// System.out.println(sqlParams);
// //参数部分
// String sqlParamsClean = sqlParams.substring(1, sqlParams.length() - 2);
// System.out.println(sqlParamsClean);
// //去掉第一个参数
// sqlParamsClean = sqlParamsClean.substring(sqlParamsClean.indexOf(",") + 1);
// System.out.println(sqlParams);
//
// newSql = insertSqlPrefix + " (" + sqlParamsClean + ")";
//
// System.out.println(newSql);
return newSql.toString();
}
return origSql;
}
private String replaceMoreBlank(String value) {
value = value.replaceAll(MORE_BLANK, BLANK);
if (StringUtils.isBlank(value) || !value.contains(MORE_BLANK)) {
return value;
}
return replaceMoreBlank(value);
}
private String replaceBlank(String value) {
value = value.replaceAll(BLANK, Strings.EMPTY);
if (StringUtils.isBlank(value) || !value.contains(BLANK)) {
return value;
}
return replaceBlank(value);
}
}
实际使用2 修改mybatis select结果值把两个空格改成空字符串
结合上述 实际使用1 “把空字符串的改成两个空格”
package cn.jiangjiesheng.edu.config.datasource;
import cn.hutool.core.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.List;
@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "query"
, args = {MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class}),
@Signature(type = Executor.class, method = "query"
, args = {MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class, CacheKey.class, BoundSql.class})})
@Component
public class MySqlSelectResultInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object obj = invocation.proceed();
try {
if (ObjectUtils.allNull(obj)) {
return obj;
}
if (!(obj instanceof List)) {
return obj;
}
List<Object> objectList = (List<Object>) obj;
for (Object object : objectList) {
this.Handle2EmptyValue(object);
}
return objectList;
} catch (Exception exception) {
log.error("ex", exception);
return obj;
}
}
private void Handle2EmptyValue(Object object) throws IllegalAccessException {
Class<?> aClass = object.getClass();
Field[] fields = ReflectUtil.getFields(aClass);//包括父类
for (Field field : fields) {
Object o = null;
try {
field.setAccessible(true);
o = field.get(object);
} catch (Exception e) {
continue;
}
if (o != null) {
if (o instanceof String) {
String s = o.toString();
if (MySqlInsertValueInterceptor.BLANK.equals(s) || MySqlInsertValueInterceptor.MORE_BLANK.equals(s)) {
field.set(object, Strings.EMPTY);
}
}
}
}
}
}
来自anyuan刘的拦截示例
package cn.jiangjiesheng.bootstrap.qpaas.interceptor;
import com.google.common.collect.Lists;
import cn.jiangjiesheng.bootstrap.commons.context.EntContext;
import cn.jiangjiesheng.bootstrap.commons.exception.BizzException;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.validation.Validation;
import net.sf.jsqlparser.util.validation.ValidationError;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
@Intercepts({@Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class, Integer.class}
)})
public class PaasDataPoolInterceptor implements Interceptor {
private static final Logger log = LoggerFactory.getLogger(PaasDataPoolInterceptor.class);
public static final CCJSqlParserManager parser = new CCJSqlParserManager();
public PaasDataPoolInterceptor() {
}
private void sqlValidator(String sql) {
Validation validation = new Validation(Lists.newArrayList(new CustomDatabaseType[]{CustomDatabaseType.SQL_92}), new String[]{sql});
List<ValidationError> errors = validation.validate();
if (!errors.isEmpty()) {
log.error("PaasDataPoolInterceptor Error {}", errors);
}
}
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
SelectTableNameModifier modifier = new SelectTableNameModifier(EntContext.getEntId());
Statement statement = parser.parse(new StringReader(sql));
if (statement instanceof Select) {
Select select = (Select)statement;
select.getSelectBody().accept(modifier);
} else if (statement instanceof Update) {
Update select = (Update)statement;
select.getTable().accept(modifier);
} else {
if (!(statement instanceof Insert)) {
throw new BizzException("不支持的语句");
}
Insert select = (Insert)statement;
select.getTable().accept(modifier);
}
Field declaredField = boundSql.getClass().getDeclaredField("sql");
declaredField.setAccessible(true);
declaredField.set(boundSql, statement.toString());
return invocation.proceed();
}
public Object plugin(Object target) {
return target instanceof StatementHandler ? Plugin.wrap(target, this) : target;
}
public void setProperties(Properties properties) {
}
}
正文到此结束