作用:深度定制mybatis的开发
场景:
1.需要干预Mybatis的SQL
2.需要统一的处理 多个Mappering文件
eg.分页(干预SQL,统一处理),乐观锁(版本对比)
3.一个业务,log业务日志
拦截器的基本开发:
1.编码
1)类implements Interceptor
2)类 标注 拦截目标:
@Intercepts(
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
)
拦截的是Executor(方法 + 参数),StatementHandler(方法 + 参数)
2.配置 mybtis-config.xml种配置
<plugins>
<plugin interceptor="com.mybatis.interceptor.MyMybatisInterceptor"></plugin>
</plugins>
MetaObject --> Mybatis底层封装的反射工具类,便于Mybatis中通过反射操作一个对象
手写分页插件:PageHelperInterceptor:
@Intercepts(
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
)
public class PageHelperInterceptor implements Interceptor {
private String queryMethodPrefix;
private String queryMethodSuffix;
private static final Logger log = LoggerFactory.getLogger(PageHelperInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
MetaObject metaObject = SystemMetaObject.forObject(invocation);
String sql = (String) metaObject.getValue("target.delegate.boundSql.sql");
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("target.delegate.mappedStatement");
String id = mappedStatement.getId();
if (id.indexOf(queryMethodPrefix) != -1 && id.endsWith(queryMethodSuffix)) {
// Page page = new Page(1);
Page page = (Page) metaObject.getValue("target.delegate.parameterHandler.parameterObject");
String countSql = "select count(*) " + sql.substring(sql.indexOf("from"));
//JDBC操作
Connection connection = (Connection) invocation.getArgs()[0];
PreparedStatement preparedStatement = connection.prepareStatement(countSql);
//假如 select count(*) from user where name = #{name}
// preparedStatement.setString(1,?);
//用parameterHandler获取sql语句中的参数
ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("target.delegate.parameterHandler");
parameterHandler.setParameters(preparedStatement);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
page.setTotalSize(resultSet.getInt(1));
if (log.isInfoEnabled())
log.info("{}",resultSet.getInt(1));
}
sql = sql + " limit " + (page.getPageIndex() - 1) + "," + page.getPageCount();
metaObject.setValue("target.delegate.boundSql.sql",sql);
}
if (log.isInfoEnabled()) {
log.info("PageHelpInterceptor....{}",sql);
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target,this);
}
@Override
public void setProperties(Properties properties) {
this.queryMethodPrefix = properties.getProperty("queryMethodPrefix");
this.queryMethodSuffix = properties.getProperty("queryMethodSuffix");
}
}
对于Sql语句的操作我们可以使用JSqlparser,简化对sql语句的操作
CCJSqlParserManager parserManager = new CCJSqlParserManager();
Select select = (Select) parserManager.parse(new StringReader("select * from user where name = 'yht'"));
PlainSelect selectBody = (PlainSelect) select.getSelectBody();
//获取表名
FromItem fromItem = selectBody.getFromItem();
JSqlparser依赖:
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>4.3</version>
</dependency>