spring boot Mybatis 拦截器实现拼接sql和修改的代码详解

网友投稿 731 2022-07-31


定义一个 SqlIntercepor 类

import com.culturalCenter.placeManhttp://age.globalConfig.Interface.InterceptAnnotation;

import org.apache.ibatis.executor.statement.StatementHandler;

import org.apache.ibatis.mapping.BoundSql;

import org.apache.ibatis.mapping.MappedStatement;

import org.apache.ibatis.plugin.*;

import org.apache.ibatis.reflection.DefaultReflectorFactory;

import org.apache.ibatis.reflection.MetaObject;

import org.apache.ibatis.reflection.SystemMetaObject;

import org.apache.ibatis.session.ResultHandler;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.annotation.Configuration;

import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.sql.Statement;

import java.util.Properties;

@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),

@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),

@Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})})

@Component

@Configuration

public class SqlInterceptor implements Interceptor {

private Logger logger = LoggerFactory.getLogger(SqlInterceptor.class);

@Override

public Object intercept(Invocation invocation) throws Throwable {

StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());

//先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseFfEDktdWhStatementHandler的成员变量mappedStatement

MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

//id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser

String id = mappedStatement.getId();

logger.info("拦截到当前请求方法的全路径名为--->: " + id);

//sql语句类型 select、delete、insert、update

String sqlCommandType = mappedStatement.getSqlCommandType().toString();

BoundSql boundSql = statementHandler.getBoundSql();

//获取到原始sql语句

String sql = boundSql.getSql();

String mSql = sql;

//获取参数

Object parameter = statementHandler.getParameterHandler().getParameterObject();

logger.info("拦截到当前请求SQL为--->: " + sql + "<------------>请求类型为: " + sqlCommandType);

logger.info("拦截到当前请求参数为--->: " + parameter);

//TODO 修改位置

//注解逻辑判断 添加注解了才拦截//InterceptAnnotation

Class> classType = Class.forName(mappedStatement.getId().substring(0, mappedStatement.getId().lastIndexOf(".")));

String mName = mappedStatement.getId().substring(mappedStatement.getId().lastIndexOf(".") + 1, mappedStatement.getId().length());

for (Method method : classType.getDeclaredMethods()) {

if (method.isAnnotationPresent(InterceptAnnotation.class) && mName.equals(method.getName())) {

InterceptAnnotation interceptorAnnotation = method.getAnnotation(InterceptAnnotation.class);

if (interceptorAnnotation.flag()) {

mSql = sql + " limit 2";

}

}

}

//通过反射修改sql语句

Field field = boundSql.getClass().getDeclaredField("sql");

field.setAccessible(true);

field.set(boundSql, mSql);

return invocation.proceed();

}

@Override

public Object plugin(Object target) {

return Plugin.wrap(target, new SqlInterceptor());

}

@Override

public void setProperties(Properties properties) {

// this.setProperties(properties);

}

自定义一个注解类实现局部处理SQL修改

InterceptAnnotation

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* 配合SqlInterceptor实现局部拦截

* */

@Target({ElementType.METHOD,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

public @interface InterceptAnnotation {

boolean flag() default true;

}

自定义数据源工厂类

SqlSessionFactoryConfig

package com.culturalCenter.placeManage.globalConfig;

import com.alibaba.druid.pool.DruidDataSource;

import org.apache.ibatis.plugin.Interceptor;

import org.apache.ibatis.session.SqlSessionFactory;

import org.mybatis.spring.SqlSessionFactoryBean;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.Primary;

import org.springframework.core.io.Resource;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**

* @author wulincheng

* @Date 2020年6月23日18:25:22

* 创建SQL连接工厂类

* */

@Configuration

public class SqlSessionFactoryConfig {

@javax.annotation.Resource

DruidDataSource dataSource;

/**

* @Autowired SqlSessionFactory sqlSessionFactory;

* SqlSession session = sqlSessionFactory.openSession();

* //创建sqlMapper

* SqlMapper sqlMapper = new SqlMapper(session);

*/

@Bean

@Primary

public SqlSessionFactory sqlSessionFactory() throws Exception {

SqlSessionFactoryBean bean = new SqlSessionFactoryBean();

bean.setDataSource(dataSource);//更多参数请自行注入

bean.setPlugins(new Interceptor[]{new SqlInterceptor()});

Resource[] resources = new PathMatchingResourcePatternResolver()

.getResources("classpath*:mapper/*.xml");

bean.setMapperLocations(resources);

return bean.getObject();

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java中进程与线程的区别(线程和进程的区别有哪些)
下一篇:Java中的HashMap为什么会产生死循环(hashmap并发死循环原理)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~