PageHelperにより、カスタムMybatisブロッキングが有効になりません.

4633 ワード

背景:
最近、会社が統一的なデータ変更記録を作るため、以前はAopに基づいてやっていたが、効率が低く、バッチ処理(insert,update,delete)操作をする際にはほとんど利用できなかった.だから私はCDC(Canal、Maxwellなどのツール)を使ってmysqlのbinlogを傍受するつもりです.すべてのテーブルにuserがあるのではないでしょうか.idフィールドなので、sqlでいくつかの処理をしなければなりません.会社は今mybatisを統一しているので、今はmybatisでsqlをブロック改造するのがいいと思います.userIdをアプリケーション層から取得し、実行するsqlに書き込みます(insert,update,deleteレコードのみ).例えば、以下のsql:update table set a=1 where name=3改造の結果、/**userId:1、traceId:123456**/update table set a=1 where name=3となり、操作でどのデータが変更されたのか、データが変更された人がどれなのかを記録することができます.
開始:
この中にはいくつかの技術点があり、あまり複雑ではありません.今日はmybatisブロッキングについて話します.実はブロックを書くのは簡単で、ネット上にはたくさんのコードがあります.コードが書き終わった後、突然一部のプロジェクトのカスタムmybatisブロッキングが有効ではないことに気づいた.そこでGoogleで検討してみると、私たちの無効なプロジェクトがPageHelperを使っているからです.そこでいくつかの大神の解決策を探して、遮断器の順序と関係があります.まず結論を述べると,MyBatisのブロッキングは責任チェーン設計モデルを採用し,複数のブロッキング間の責任チェーンは動的エージェントによって組織されている.ブロック内のinterceptメソッドにはinvocationがあるのが一般的です.Proceed()文は、ブロッキング責任チェーンを後方に伝達する役割を果たし、本質的に動的エージェントのinvokeである.
PageHelperはinterceptメソッドで実行後invocationを実行しなかった.Proceed()は、責任チェーンを伝え続けていないことを意味します(彼は自分の考えを持っているかもしれません).だから彼は私たちのブロックに入っていません.
注意、黒板をたたく:
A.すべてのブロッキングが優先順位を指定しなければならないわけではありません.ブロックの呼び出し順序は2つに大きく分けられ、1つ目はブロックされた異なるオブジェクトである.例えば、ブロックExecutorとブロックStatementHandlerは異なるブロックオブジェクトに属し、この2つのブロックは全体的に実行される論理的に異なり、Executorのqueryメソッド実行中にStatementHandlerが呼び出される.
したがって、StatementHandlerはExecutor実行中のサブプロシージャに属します.したがって、この2つの異なるカテゴリのプラグインは、構成時にExecutorのブロッキングを実行してからStatementHandlerの番になるに違いありません.したがって,この場合にブロッキングを配置する順序は重要ではなく,MyBatis論理では順序を制御している.だからもしあなたがExecutorタイプのブロックであれば、StatementHandlerタイプのブロックであれば、彼の順序を気にしなくてもいいです.つまり、タイプがExecutorのブロック順序を定義する必要があります.
B.タイプはすべてExecutorのブロッキング順序の問題です:もしあなたのブロッキング定義の順序がこのような場合(sqlSessionFactory.getConfiguration()を取得して中のInterceptorChainを見てから各interceptorの順序を見ることができます):彼の実行の順序は先に1,2,3を実行するのではなく、実行の順序は3,2,1です.
Interceptor3:{
    Interceptor2: {
        Interceptor1: {
            target: Executor
        }
    }
}

この構成から容易に分かるように,将来実行する際には必ず3>2>1>Executor>1>2>3の順に実行される.なぜ3>2>1>Executorの後に1>2>3があるのか分からない人もいるかもしれませんが、これはエージェントを使用する場合、エージェントメソッドを呼び出した後も、他の処理を継続できるためです.処理が終了したら,エージェントメソッドの戻り値を引き続き外に戻せばよい.
C(ソリューション).PageHelperはExcetorタイプのブロッカーなので、前の2つの理論に従って、PageHelperブロッカーの前で実行するには、私たち自身のブロッカーを彼のブロッカーの後ろに追加する必要があります.
どうすればいいの?私たちはこのような方法で行うことができます.
PageHelperAutoConfigurationのコードを見てみましょう.このクラスには@AutoConfigureAfter(MybatisAutoConfiguration.class)注記があります.これは、MybatisAutoConfigurationのロードが完了した後、自分のロードを実行していることを示しています.では、私たちはstarterではありませんが、このような操作で私たちの要求を実現することができます.
(1)src/main/resources/META-INFディレクトリの下にspringを作成する.factoriesのファイル(2)spring.factoriesの内容は:org.springframework.boot.autoconfigure.EnableAutoConfiguration= com.llyt.exculd.TestLogAutoConfigurationこのcom.llyt.exculd.TestLogAutoConfigurationは、あなた自身の構成クラスの全パスです.このクラスのコードは後ろにあります.(3)TestLogAutoConfigurationコード:
@Configuration
@AutoConfigureAfter(PageHelperAutoConfiguration.class)
public class TestLogAutoConfiguration {
    @Autowired
    private List sqlSessionFactoryList;

    @PostConstruct
    public void addMyInterceptor() {
        ExampleOnePlugin e = new ExampleOnePlugin();
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            sqlSessionFactory.getConfiguration().addInterceptor(e);
        }
    }
}

これで、この方法はOKです.しかし、このクラスのaddMyInterceptorメソッドは、PageHelperAutoConfigurationのaddPageInterceptor()メソッドよりも先に実行される可能性があります.これは、pageHelperブロッキングの前にブロッキングが常に追加されていることを意味し、彼は常にPageHelperブロッキングの後ろで実行されていることを意味します.この場合、spring bootプライマリクラスに@ComponentScan("****")を構成し、クラスがスキャンされる可能性があります.これが原因です.
@AutoConfigureAfter(A.class)を構成するのではなく、クラスが必ずAクラスの後ろで実行されていることを示す知識があります.
構成クラスがspringの場合.factoriesで構成されており、クラスが自分のSpring Boot起動クラスにスキャンされた場合、クラスは優先的にスキャンされ、構成クラスが順序に要求された場合にエラーが発生します.
では、どうすればいいのでしょうか.
解決策は2つあります.
a.騒々しい操作を使用する.
独自の構成クラスを特別なパッケージの下に置くと、Spring Bootを使用してクラススキャンを開始しません.完全にspringを通過します.factories読み出し構成でこの目的を達成できます.例えば、あなたの@ComponentScanがスキャンしたバッグはcomです.bb.ccでは、この構成クラスをcomに置きます.bb.ddバッグの下.
b.慣れていないと思ったらexcludeFiltersを使ってください.
@ComponentScan(basePackages = {"com.llyt"},  excludeFilters = @ComponentScan.Filter(
     type = FilterType.REGEX,
     pattern = "com.llyt.exculd.*"))

あなたの構成クラスをcomに置きます.llyt.exculdパッケージの下でいいです.
これで、mybatisブロッキングの無効化の問題は、終わりました.
参考文献:http://xtong.tech/2018/08/01/MyBatis%E6%8B%A6%E6%88%AA%E5%99%A8%E5%9B%A0pagehelper%E8%80%8C%E5%A4%B1%E6%95%88%E7%9A%84%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/Interceptor.md