MyBatis-Plugins


MyBatis 允許在已映射語句執行過程中的某一點進行攔截調用。默認情況下,MyBatis 允許使用插件來攔截的方法調用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

除了用插件來修改 MyBatis 核心行為之外,還可以通過完全覆蓋配置類來達到目的。只需繼承后覆蓋其中的每個方法,再把它傳遞到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。

 

一、可攔截的接口

1.Executor-執行器

public interface Executor {
    // 不需要 ResultHandler
    ResultHandler NO_RESULT_HANDLER = null;
    // 更新
    int update(MappedStatement ms, Object parameter) throws SQLException;
    // 查詢(先查緩存),帶分頁,BoundSql
    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
    // 查詢,帶分頁
    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
    // 查詢游標
    <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
    // 刷新(Statement)批處理語句
    List<BatchResult> flushStatements() throws SQLException;
    // 提交事務,參數為是否要強制
    void commit(boolean required) throws SQLException;
    // 回滾事務,參數為是否要強制
    void rollback(boolean required) throws SQLException;
    // 創建 CacheKey
    CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
    // 判斷是否緩存了,通過 CacheKey
    boolean isCached(MappedStatement ms, CacheKey key);
    // 清理 Session(本地一級) 緩存
    void clearLocalCache();
    // 延遲加載
    void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
    // 獲取事務
    Transaction getTransaction();
    // 關閉連接
    void close(boolean forceRollback);
    // 是否關閉
    boolean isClosed();
    // 設置 Executor
    void setExecutorWrapper(Executor executor);
}

2.ParameterHandler-參數處理器

public interface ParameterHandler {
    // 獲取參數
    Object getParameterObject();
    // 設置參數
    void setParameters(PreparedStatement ps) throws SQLException;
}

3.ResultSetHandler-結果集處理器

public interface ResultSetHandler {
    // 將結果集轉化成 List
    <E> List<E> handleResultSets(Statement stmt) throws SQLException;
    // 將結果集轉化成 Cursor
    <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
    // 處理存儲過程的 OUT(輸出) 參數
    void handleOutputParameters(CallableStatement cs) throws SQLException;
}

4.StatementHandler-SQL語句處理器

public interface StatementHandler {
    // 准備語句
    Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;
    // 參數處理
    void parameterize(Statement statement) throws SQLException;
    // 批量處理
    void batch(Statement statement) throws SQLException;
    // 更新處理
    int update(Statement statement) throws SQLException;
    // 查詢處理,結果給 ResultHandler
    <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;
    <E> Cursor<E> queryCursor(Statement statement) throws SQLException;
    // 獲取綁定 SQL 語句
    BoundSql getBoundSql();
    // 獲取參數處理器
    ParameterHandler getParameterHandler();
}

 

二、自定義插件

實現 Interceptor 接口,並指定想要攔截的方法簽名。最后在 xml 文件中配置全類名即可。

1.bean

@Alias("myUser")
public class MyUser implements Serializable {
    private Integer id;
    private String name;
    private Integer age;

2.dao接口

public interface MyUserMapperAnnotation {
    @Select("select * from myuser")
    List<MyUser> selectMyUser(String a);
}

3.mybatis-config.xml

<?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">
<configuration>
    <!-- 注意 plugins 在配置文件中的位置
        properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers? -->
    <plugins>
        <plugin interceptor="com.plugins.ExamplePlugin">
            <property name="someProperty" value="100"/>
        </plugin>
    </plugins>

    <environments default="development-mysql">
        <environment id="development-mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.8.136:3306/mybatis?allowMultiQueries=true"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.dao.MyUserMapperAnnotation"/>
    </mappers>
</configuration>

4.ExamplePlugin

/**
 * @Intercepts 攔截器注解,包括一個或多個 @Signature
 * @Signature 攔截的目標類信息,包括 type、method、args
 * * type 要攔截的接口類型
 * * method 接口中的方法名
 * * args 方法的所有入參類型
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class ExamplePlugin implements Interceptor {
    /**
     * 攔截目標對象的目標方法的執行,將自定義邏輯寫在該方法中
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("ExamplePlugin...intercept:" + invocation.getMethod());

        // MetaObject 是 Mybatis 提供的一個用於訪問對象屬性的對象
        MetaObject metaObject = SystemMetaObject.forObject(invocation);

        System.out.println("當前攔截到的對象:" + metaObject.getValue("target"));
        System.out.println("SQL語句:" + metaObject.getValue("target.delegate.boundSql.sql"));
        System.out.println("SQL語句入參:" + metaObject.getValue("target.delegate.parameterHandler.parameterObject"));
        System.out.println("SQL語句類型:" + metaObject.getValue("target.delegate.parameterHandler.mappedStatement.sqlCommandType"));
        System.out.println("Mapper方法全路徑名:" + metaObject.getValue("target.delegate.parameterHandler.mappedStatement.id"));

        // 修改 SQL 語句
        String newSQL = metaObject.getValue("target.delegate.boundSql.sql") + " limit 2";
        metaObject.setValue("target.delegate.boundSql.sql", newSQL);
        System.out.println("修改后SQL語句:" + newSQL);

        // 返回執行結果
        return invocation.proceed();
    }

    /**
     * 為目標對象創建一個代理對象,使用 Plugin.wrap(target,this) 即可
     * @param target 上次包裝的代理對象
     * @return 本次包裝過的代理對象
     */
    @Override
    public Object plugin(Object target) {
        System.out.println("ExamplePlugin...plugin:" + target);
        return Plugin.wrap(target, this);
    }

    /**
     * 獲取自定義配置參數
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        System.out.println("插件配置信息:" + properties);
        System.out.println("someProperty:" + properties.get("someProperty"));
    }
}

5.Main

public static void main(String[] args) throws IOException {
    SqlSession session = null;
    try {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        session = sqlSessionFactory.openSession();
        MyUserMapperAnnotation mapper = session.getMapper(MyUserMapperAnnotation.class);

        System.out.println(mapper.selectMyUser("asdsad"));
    } finally {
        if (session != null) {
            session.close();
        }
    }
}

 

 


http://www.mybatis.org/mybatis-3/zh/configuration.html#plugins

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM