MyBatis外掛

LZC發表於2021-07-20

MyBatis 允許你在對映語句執行過程中的某一點進行攔截呼叫。預設情況下,MyBatis 允許使用外掛來攔截的方法呼叫包括:

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

這些類中方法的細節可以透過檢視每個方法的簽名來發現,或者直接檢視 MyBatis 發行包中的原始碼。 如果你想做的不僅僅是監控方法的呼叫,那麼你最好相當瞭解要重寫的方法的行為。 因為在試圖修改或重寫已有方法的行為時,很可能會破壞 MyBatis 的核心模組。 這些都是更底層的類和方法,所以使用外掛的時候要特別當心。

透過 MyBatis 提供的強大機制,使用外掛是非常簡單的,只需實現 Interceptor 介面,並指定想要攔截的方法簽名即可。

@Intercepts({
        @Signature(
                type = StatementHandler.class,
                // StatementHandler.prepare方法
                method = "prepare",
                // StatementHandler.prepare方法的引數型別
                args = {Connection.class,Integer.class}
        )
})
public class ExamplePlugin implements Interceptor {

    private Properties properties = new Properties();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql() + " limit 0,2";
        // 利用反射,修改原來的sql
        Field sqlField = boundSql.getClass().getDeclaredField("sql");
        sqlField.setAccessible(true); // 解除私有限定
        sqlField.set(boundSql, sql);
        // implement pre processing if need
        Object returnObject = invocation.proceed();
        // implement post processing if need
        return returnObject;
    }

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

    @Override
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
<plugins>
    <plugin interceptor="com.example.demo.ExamplePlugin">
        <property name="someProperty" value="100"/>
    </plugin>
</plugins>
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章