Mybatis四大核心组件
Executor
执行和数据库相关的方法(不是指具体的SQL语句的执行)
StatementHandler
执行和数据库相关的具体SQL语句
ParameterHandler
mybatis提供的参数处理器,映射参数。比如将传入的对象,映射到具体的SQL参数上
ResultSetHandler
对于查询数据结果集的映射和处理
而我们的插件应该插入到StatementHandler的上面
package com.hand.mybatis.demo.plugins;
import com.hand.mybatis.demo.entity.MybatisSql;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
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 java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
/**
* @author dell
*/
@Intercepts({@Signature(
type= StatementHandler.class, //拦截的目标是四大对象的哪个对象,这里选择的是StatementHandler
method = "prepare",//StatementHandler中的哪一个方法
args = {Connection.class,Integer.class})}) //prepare方法中的所需的参数
public class MyPlugins implements Interceptor {
/**
*
* @param invocation :整个拦截器的一个封装
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
//要在SQL执行之前,执行一条插入数据库的语句
Connection connection = (Connection)invocation.getArgs()[0];
/**
* 获取到执行的SQL语句
*/
String sql = statementHandler.getBoundSql().getSql();
System.out.println("原始的SQL:"+sql);
/**
* 获取到SQL执行的参数
*/
ParameterHandler parameterHandler = statementHandler.getParameterHandler();
String sqlParam = parameterHandler.getParameterObject().toString();
System.out.println("SQL的参数:"+ sqlParam);
//在执行SQL之前,还可以更改原SQL,比如说增加limit分页
String insertDbSql = "insert into mybatissql(sql_insert,sql_param,create_time) values("+"'"+sql+"'"+','+"\""+sqlParam+"\""+','+"now())";
System.out.println("插入语句为:"+insertDbSql);
PreparedStatement preparedStatement = connection.prepareStatement(insertDbSql);
preparedStatement.execute();
connection.commit();
//执行完逻辑之后,推进拦截链
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
//target :目标对象
//interceptor:代理对象
return Plugin.wrap(target,this);
}
@Override
public void setProperties(Properties properties) {
}
}
知识点:
- 注解上的type,表示你要拦截的对象,这里选择的是StatementHandler,因为StatementHandler操作的是具体的SQL,在该组件前进行拦截,我们可以获取到SQL和SQL的参数
- method是指StatementHandler的方法,选择的是prepare方法
- args自然就是指prepare方法的参数
更新数据库的操作,需要commit,关于mybatis的插件的标签,需要按照一定的顺序来配置