MybatisはSQLクエリのインターセプションと変更の詳細を実装します

MybatisはSQLクエリのインターセプションと変更の詳細を実装します

序文

インターセプターの機能の 1 つは、特定のメソッドの呼び出しをインターセプトできることです。インターセプトされたメソッドの実行の前後にロジックを追加することも、インターセプトされたメソッドを実行する代わりに、インターセプトされたメソッドを実行するときに独自のロジックを実行することもできます。

Mybatis インターセプターを設計した当初の目的の 1 つは、Mybatis の固有のロジックを変更することなく、ユーザーが特定のタイミングで独自のロジックを実装できるようにすることです。たとえば、すべての SQL に対して固定操作を実行したり、SQL クエリに対してセキュリティ チェックを実行したり、関連する SQL クエリ ログを記録したりしたいとします。

Mybatis は、カスタム インターセプターを実装できる Interceptor インターフェースを提供します。

 パブリックインターフェースインターセプター{
 オブジェクト intercept(Invocation invocation) は Throwable をスローします。
 オブジェクトプラグイン(オブジェクトターゲット);
 void setProperties(プロパティプロパティ);
}

インターフェースには3つのメソッド定義が含まれています

インターセプトメソッドは、インターセプトオブジェクトに対する特定の処理メソッドです。渡される Invocation には、インターセプト対象クラスの強度、インターセプトメソッド、およびメソッドの入力パラメータグループが含まれます。呼び出し手順を使用して元の関数を実行します。

プラグインはインターセプトするかどうかを決定します。インターセプトが不要な場合は、ターゲットが直接返されます。インターセプトが必要な場合は、Plugin クラスの wrap 静的メソッドが呼び出されます。現在のインターセプターがインターフェイスを実装している場合はプロキシ オブジェクトが返され、そうでない場合は直接返されます (プロキシ モードの設計を思い出してください)。プロキシ オブジェクトは、実際には InvocationHandler インターフェイスを実装する Plugin クラスのインスタンスです。InvocationHandler インターフェイスには、コールバック メソッドの呼び出しメソッドのみが含まれます。

プロキシ オブジェクトのインターフェイス メソッドが実行されると、プラグインの呼び出しメソッドが呼び出され、実行されるオブジェクト、メソッド、およびパラメーターが呼び出しオブジェクトにパッケージ化され、インターセプターのインターセプト メソッドに渡されます。呼び出しは、インターセプトされた元のメソッドを実行するための procced メソッドを定義します。

プラグインクラスの定義

パブリッククラスPluginはInvocationHandlerを実装します{
 
 プライベートオブジェクトターゲット;
 プライベートインターセプターインターセプター;
 プライベート Map、Set> signatureMap;
 
 プライベートプラグイン(オブジェクトターゲット、インターセプターインターセプター、マップ、Set> signatureMap) {
  this.target = ターゲット;
  this.interceptor = インターセプター;
  this.signatureMap = 署名マップ;
 }
 
 パブリック静的オブジェクトラップ(オブジェクトターゲット、インターセプターインターセプター) {
  マップ、セット> signatureMap = getSignatureMap(インターセプター);
  クラスタイプ = target.getClass();
  クラス[]インターフェース = getAllInterfaces(type, signatureMap);
  インターフェースの長さが0より大きい場合
   Proxy.newProxyInstance() を返します。
     type.getClassLoader()、
     インターフェース、
     新しいプラグイン(ターゲット、インターセプター、シグネチャマップ));
  }
  ターゲットを返します。
 }
 
 パブリックオブジェクトinvoke(オブジェクトプロキシ、メソッドメソッド、オブジェクト[]引数)throwsThrowable{
  試す {
   メソッドを signatureMap.get(method.getDeclaringClass()); に設定します。
   メソッドが null の場合、methods.contains(method) は次のように記述されます。
    interceptor.intercept(new Invocation(target, method, args)) を返します。
   }
   メソッドを呼び出します(ターゲット、引数)。
  } キャッチ (例外 e) {
   ExceptionUtil.unwrapThrowable(e) をスローします。
  }
 }
 
 プライベート静的マップ、Set> getSignatureMap(インターセプターインターセプター) {
  インターセプト interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
  if (interceptsAnnotation == null) { // 問題 #251
   throw new PluginException("インターセプターに @Intercepts アノテーションが見つかりません " + interceptor.getClass().getName());   
  }
  署名[] sigs = interceptsAnnotation.value();
  Map、Set> signatureMap = new HashMap、Set>();
  (署名 sig : sigs) {
   メソッドを設定します = signatureMap.get(sig.type());
   if (メソッド == null) {
    メソッド = 新しい HashSet();
    signatureMap.put(sig.type(), メソッド);
   }
   試す {
    メソッド method = sig.type().getMethod(sig.method(), sig.args());
    メソッドを追加します。
   } キャッチ (NoSuchMethodException e) {
    throw new PluginException("" + sig.type() + " に " + sig.method() + " という名前のメソッドが見つかりませんでした。原因: " + e, e);
   }
  }
  署名マップを返します。
 }
 
 プライベート静的Class[] getAllInterfaces(クラス型、マップ、セット> signatureMap) {
  Set> インターフェース = new HashSet>();
  while (type != null) {
   (クラスcの場合: type.getInterfaces()) {
    署名マップにキーが含まれている場合(c)
     インターフェースを追加します。
    }
   }
   タイプ = type.getSuperclass();
  }
  戻り値:interfaces.toArray(新しいClass[interfaces.size()]);
 }
 
}

setProperties メソッドは、その名前が示すように、プロパティを設定するために使用されます。 Bean プロパティを初期化する方法は多数ありますが、これはその 1 つです。

Mybatis は、現在のクラスがインターセプターであることを宣言するための @Intercepts アノテーションを提供します。その値は @Signature 配列であり、インターセプトされるインターフェース、メソッド、および対応するパラメーター タイプを示します。

@Intercepts({@Signature(メソッド = "準備"、タイプ = StatementHandler.class、引数 = {Connection.class})、
    @Signature(メソッド = "query"、タイプ = StatementHandler.class、引数 = {java.sql.Statement.class、ResultHandler.class})})
パブリッククラス TenantInterceptor は Interceptor を実装します {
.....

たとえば、上記のクラス宣言では、最初の Signature アノテーションは StatementHandler クラスの下にある入力パラメータ (prepare という名前の Connection メソッド) をインターセプトします。

2 番目の Signature アノテーションは、2 つの入力パラメータ (Statement 型と ResultHandler 型) を含む StatementHandler クラスのクエリ メソッドをインターセプトします。

最後に、宣言された Interceptor を有効にするには、mybatis プラグに登録する必要があります。

  <!-- mybatis を設定する -->
  <bean id="sqlSessionFactory" クラス="org.mybatis.spring.SqlSessionFactoryBean">
    <プロパティ名="データソース" ref="データソース"/>
    <プロパティ名="configLocation" 値="classpath:mybatis/mybatis-config.xml"/>
    <!-- マッパースキャン -->
    <プロパティ名="mapperLocations" 値="classpath:mybatis/*/*.xml"/>
    <プロパティ名="プラグイン">
      <配列>
        <!-- 独自のインターセプターを登録する -->
        <bean id="paginationInterceptor" class="xxx.xxx.TenantInterceptor">
        </bean>
      </配列>
    </プロパティ>
  </bean>

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Mybatis で SQL クエリに複数のパラメータを渡す方法
  • Mybatis の SQL ノードの詳細な分析

<<:  実際のプロジェクトでElementUIを使用する手順の詳細な説明

>>:  Vue 仮想 Dom から実際の Dom への変換

推薦する

nginxのデフォルトポートを変更する方法の詳細な説明

まず設定ファイルがどこにあるか調べる nginx.confはどこにありますかこれらのディレクトリを調...

60件のページング事例と優れた実践例を推奨

<br />構造と階層により複雑さが軽減され、読みやすさが向上します。記事やサイトが整理...

Dockerコンテナのデータを復元する方法

プロジェクトのテスト環境データベースのデータが失われてしまったので、記録しておきたいと思います。当時...

docker nginxコンテナの起動とローカルへのマウントの詳細な説明

まず、nginx コンテナ内の構造:コンテナを入力します: docker exec -it b511...

Linux で at および cron スケジュールタスクをカスタマイズする方法

Linux システムには 2 種類のスケジュールされたタスクがあります。1 つは 1 回だけ実行され...

Centos7 に Nginx 統合 Lua サンプル コードをインストール

序文私が使用しているパソコンはMacで、OSはmacOS Mojaveです。コンピュータに仮想マシン...

docker redis5.0 clusterの実装 クラスタ構築

システム環境: Ubuntu 16.04LTSこの記事では、6 つの Docker コンテナを使用し...

プライベートレジストリ内の画像を照会または取得する方法

Dockerはプライベートレジストリ内のイメージを照会または取得するために、 docker 検索 1...

MySQL複合インデックスの詳細な研究

複合インデックス (結合インデックスとも呼ばれます) は、複数の列に対して作成されるインデックスです...

Nginx キャッシュ ファイルと動的ファイルの自動バランス設定スクリプト

nginx Nginx (エンジン x) は、高性能な HTTP およびリバース プロキシ サーバー...

K8Sの5つのコントローラーの紹介と使用

目次k8sのコントローラータイプポッドとコントローラの関係デプロイメント(ステートレスアプリケーショ...

HTML テーブル タグ チュートリアル (34): 行スパン属性 ROWSPAN

複雑なテーブル構造では、一部のセルが水平方向に複数のセルにまたがるため、行間属性 ROWSPAN を...

Dockeにredisをインストールする方法

1. redisイメージを検索する docker 検索 redis 2. Redisイメージをダウン...

Vue の NetEase Cloud Music Player インターフェースを模倣したシンプルな実装プロセス

仕事のプロジェクトのニーズにより、曲の再生が必要となり、さまざまな資料を参考にして、NetEase ...

Windows に MySQL 8.0.16 をインストールする手順とエラーの解決方法

1. はじめに: mysql8以降は、これまでよく使われていたバージョンと比べてかなり変更点が大きい...