181. Spring Boot MyBatis Custom Plugin


 

【Video & Communication Platform】

à SpringBoot Video 

http://study.163.com/course/introduction.htm?courseId=1004329008&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

à  SpringCloud Video

http://study.163.com/course/introduction.htm?courseId=1004638001&utm_campaign=commission&utm_source=400000000155061&utm_medium=share

à Spring Boot source code 

https://gitee.com/happyangellxq520/spring-boot

à Spring Boot communication platform 

http://412887952-qq-com.iteye.com/blog/2321532

 

Origin of need:

       Someone asked in the discussion area ( portal ) of NetEase Cloud Classroom : Teacher, what is the implementation principle of PageHelper ? This principle, of course, cannot be explained in one or two sentences, so I intend to write an article here.

 

Outline of this section:

wrote
1. Ideas for custom plugins
2. Custom plugin coding: record SQL

 

 

First, the idea of ​​custom plug-ins

 

1.1 Implement the interface Interceptor

 

If you want to customize the plug- in in mybatis , then you need to implement the following interface:

org.apache.ibatis.plugin.Interceptor

     

  There are three main methods in this interface:

 

 

Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
 

 

 

       So what can all three do?

 

( 1 ) Method plugin(Object target)

The plugin method is used by the interceptor to encapsulate the target object. Through this method, we can return the target object itself or return a proxy for it. When the proxy is returned, we can intercept the methods in it to call the intercept method, and of course other methods can also be called.

 

2)方法setProperties(Properties properties)

The setProperties method is used to specify some properties in the Mybatis configuration file.

 

3)方法intercept(Invocation invocation)

定义自己的Interceptor最重要的是要实现plugin方法和intercept方法,在plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象。而intercept方法就是要进行拦截的时候要执行的方法。

 

 1.2 使用@Bean注入自定义的Plugin

       spring boot中可以使用如下代码进行注入:

 

@Bean
    public SQLStatsInterceptor sqlStatsInterceptor(){
        SQLStatsInterceptor sqlStatsInterceptor = new SQLStatsInterceptor();
        Properties properties = new Properties();
        properties.setProperty("dialect", "mysql");
         sqlStatsInterceptor.setProperties(properties);
       return sqlStatsInterceptor;
}
 

 

       如果是在spring中使用xml配置的方式的话,可以使用如下的方式进行注入:

<configuration>
    <plugins>
        <plugin interceptor="com.kfit.config.interceptor.SQLStatsInterceptor">
            <property name="dialect" value="mysql" />
        </plugin>
    </plugins>
</configuration>
 

 

 

 

1.3 思路总结

       上面那多废话,简单来说就是:其一需要定义实现接口Interceptor;其二就是要配置注入。千言万语, 不如一句代码,还是写个例子看看效果吧。

                             

二、自定义插件编码:记录SQL

 

2.1 需求描述

       在这里实现:把Mybatis所有执行的sql都记录下来。

 

2.2 代码实现分析

通过对 MyBatis org.apache.ibatis.executor.statement.StatementHandler中的prepare 方法进行拦截即可。

 

 

2.3 代码实现

2.3.1实现类SQLStatsInterceptor实现接口Interceptor

package com.kfit.config.interceptor;
import java.sql.Connection;
import java.util.Properties;
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;
 
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class,Integer.class})})
public class SQLStatsInterceptor implements Interceptor {
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
       StatementHandler statementHandler= (StatementHandler) invocation.getTarget();
       BoundSql boundSql = statementHandler.getBoundSql();
       System.out.println(boundSql.getSql());
       return invocation.proceed();
    }
 
    @Override
    public Object plugin(Object target) {
       return Plugin.wrap(target, this);
    }
 
    @Override
    public void setProperties(Properties properties) {
        String dialect = properties.getProperty("dialect");
        System.out.println("dialect="+dialect);
    }
}

 

代码分析:

1)首先SQLStatsInterceptor类实现了接口Interceptor

2)需要重写3个方法,核心的拦截处理方法是intercept,在这个方法中可以获取到对应的绑定的sql,在这里作为演示只是打印了SQL,如果需要可以保存起来。

3)在方法上有一个很重要的注解@Intercepts,在此注解上配置的注解说明了要拦截的类(type=StatementHandler.class),拦截的方法(method="prepare"),方法中的参数(args={Connection.class,Integer.class}),也就是此拦截器会拦截StatementHandler类中的如下方法:

 

Statement prepare(Connection connection, Integer transactionTimeout)

  

      

 

这里顺带提一下,可以拦截的类:

StatementHandler (prepare, parameterize, batch, update, query)

ResultSetHandler (handleResultSets, handleOutputParameters)

ParameterHandler (getParameterObject, setParameters)

Executor (update, query, flushStatements, commit, rollback,getTransaction, close, isClosed)

 

 

2.3.2定义配置类进行注入

@Configuration
public class MyBatisConfiguration {
    @Bean
    public SQLStatsInterceptor sqlStatsInterceptor(){
        SQLStatsInterceptor sqlStatsInterceptor = new SQLStatsInterceptor();
        Properties properties = new Properties();
        properties.setProperty("dialect", "mysql");
         sqlStatsInterceptor.setProperties(properties);
       return sqlStatsInterceptor;
    }
}

 

       Here you can test it. Once you understand the custom Plugin , then you will understand the implementation of PageHelper .

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326277320&siteId=291194637