mybatis的使用及源码分析(六) mybatis自定义plugin

使用Mybatis的时候,会使用到各种插件,如PageHelper(分页插件)等,下面介绍自定义plugin的方法

Mybatis插件又称拦截器,Mybatis采用责任链模式,通过动态代理组织多个插件(拦截器),通过这些插件可以改变Mybatis的默认行为。MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis允许使用插件来拦截的方法调用包括:

Executor (update, query, flushStatements, commit, rollback,getTransaction, close, isClosed) 拦截执行器的方法;
ParameterHandler (getParameterObject, setParameters) 拦截参数的处理;
ResultSetHandler (handleResultSets, handleOutputParameters) 拦截结果集的处理;
StatementHandler (prepare, parameterize, batch, update, query) 拦截Sql语法构建的处理;

自定义一个Plugin:
本项目搭建源码:https://github.com/zhuquanwen/mybatis-learn/releases/tag/with-plugin
搭建过程:
https://blog.csdn.net/u011943534/article/details/104911104文章基础上搭建,有些过程不详细描述.

1、自定义一个类实现Interceptor

Signature注解中 type支持上面说的四种类型:Executor、ParameterHandler、ResultSetHandler、StatementHandler,method对应某个type类型中的方法名 ,args是方法参数的类对象。
plugin方法,默认使用Plugin.wrap(target, this)就好,setProperties可以注入配置参数,intercept可以做一些业务处理,比如这里我把SQL语句输出,把耗时计算输出。

package com.learn.zqw.plugin;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

/**
 * //TODO
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/6/27 12:58
 * @since jdk1.8
 */
@Slf4j
@Intercepts(@Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class TestPlugin implements Interceptor {
    private Properties properties;
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object paramter = args[1];
        String sqlid = mappedStatement.getId();
        BoundSql boundSql = mappedStatement.getBoundSql(paramter);
        String sql = boundSql.getSql();
        log.debug(sql);
        long start = System.currentTimeMillis();

        Object proceed = invocation.proceed();
        long end = System.currentTimeMillis();
        log.debug("耗时:" + (end - start) + "ms");
        return proceed;

    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

2、配置plugin
如下添加plugins标签,并可配置输入properties参数

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis的主配置文件-->
<configuration>

    <!--自定义typeHandler-->
    <typeHandlers>
        <typeHandler handler="com.learn.zqw.handler.SexEnumTypeHandler"
                     javaType="com.learn.zqw.generator.domain.SexEnum"
                     jdbcType="SMALLINT"/>
    </typeHandlers>

    <plugins>
        <plugin interceptor="com.learn.zqw.plugin.TestPlugin">
            <property name="testKey" value="testVal"/>
        </plugin>
    </plugins>

    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务类型-->
            <transactionManager type="JDBC" />
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_learn?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>


    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>

        <mapper resource="com/learn/zqw/IUserMapper.xml" />
        <mapper resource="com/learn/zqw/generator/mapper/StudentMapper.xml" />
        <mapper resource="com/learn/zqw/generator/mapper/BirdMapper.xml" />

        <!--可以直接把每个xml作配置,也可以使用包扫描,使用包扫描,如果使用纯注解方式,也可以把对应的.xml文件删除-->
        <!--<mapper resource="com/learn/zqw/sqlannotation/mapper/BookMapper.xml" />-->
        <!-- <mapper resource="com/learn/zqw/sqlannotation/mapper/LibraryMapper.xml" />-->
        <package name="com.learn.zqw.sqlannotation.mapper"/>
    </mappers>
    

</configuration>

3、测试

package com.learn.zqw.plugin;

import com.learn.zqw.generator.domain.Student;
import com.learn.zqw.generator.mapper.StudentMapper;
import lombok.Cleanup;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.io.IOException;
import java.io.InputStream;

/**
 * //TODO
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/6/27 14:05
 * @since jdk1.8
 */

@RunWith(JUnit4.class)
public class PluginTests {
    /**
     * 测试按照ID查询
     * */
    @Test
    public void Test1() throws IOException {
        //1.读取配置文件
        @Cleanup InputStream in = Resources.getResourceAsStream ("SqlMapConfig.xml");
        //2. 创建SqlSessionFactory
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession session = factory.openSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        //按主键查询
        Student student = mapper.selectByPrimaryKey(1);
        Assert.assertNotNull(student);
        System.out.println(student);
    }
}

执行后输出了想要的日志:

[2020/06/27 14:10:09,897] [DEBUG] [org.apache.ibatis.io.DefaultVFS:102] - Reader entry: <?xml version="1.0" encoding="UTF-8"?>
[2020/06/27 14:10:09,898] [DEBUG] [org.apache.ibatis.io.ResolverUtil:256] - Checking to see if class com.learn.zqw.sqlannotation.mapper.BookMapper matches criteria [is assignable to Object]
[2020/06/27 14:10:09,899] [DEBUG] [org.apache.ibatis.io.ResolverUtil:256] - Checking to see if class com.learn.zqw.sqlannotation.mapper.LibraryMapper matches criteria [is assignable to Object]
[2020/06/27 14:10:09,969] [DEBUG] [com.learn.zqw.plugin.TestPlugin:33] - select 
     
    id, name, real_name
   
    from student
    where id = ?
[2020/06/27 14:10:09,977] [DEBUG] [org.apache.ibatis.transaction.jdbc.JdbcTransaction:136] - Opening JDBC Connection
Sat Jun 27 14:10:10 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
[2020/06/27 14:10:10,220] [DEBUG] [org.apache.ibatis.datasource.pooled.PooledDataSource:424] - Created connection 370869802.
[2020/06/27 14:10:10,220] [DEBUG] [org.apache.ibatis.transaction.jdbc.JdbcTransaction:100] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@161b062a]
[2020/06/27 14:10:10,228] [DEBUG] [com.learn.zqw.generator.mapper.StudentMapper.selectByPrimaryKey:143] - ==>  Preparing: select id, name, real_name from student where id = ? 
[2020/06/27 14:10:10,254] [DEBUG] [com.learn.zqw.generator.mapper.StudentMapper.selectByPrimaryKey:143] - ==> Parameters: 1(Integer)
[2020/06/27 14:10:10,271] [DEBUG] [com.learn.zqw.generator.mapper.StudentMapper.selectByPrimaryKey:143] - <==      Total: 1
[2020/06/27 14:10:10,272] [DEBUG] [com.learn.zqw.plugin.TestPlugin:38] - 耗时:303ms
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章