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 への変換

推薦する

ゲーム着物メモ問題の簡単な分析

本日、ゲームを再起動した後、バックアップしたデータをターゲットデータベースにインポートできないことが...

マークアップ言語 - リスト

標準化されたデザインソリューション - マークアップ言語とスタイルマニュアルWeb 標準ソリューショ...

Nginx+tomcat ロードバランシングクラスタの実装方法

実験環境は以下のとおりですここでは、4 台のサーバー (1 台の nginx、負荷用の 2 台の t...

MySQL 学習のまとめ: InnoDB ストレージ エンジンのアーキテクチャ設計の予備的な理解

1. ストレージエンジン前のセクションでは、SQL 実行プランは、エグゼキュータ コンポーネントがス...

React Stateの状態とライフサイクルの実装方法

1. コンポーネントの実装方法:組件名稱首字母必須大寫1. JS関数を通じてコン​​ポーネントを実装...

MySQL テーブル名の大文字と小文字の選択

目次1. 大文字と小文字の区別を決定するパラメータ2. パラメータ変更に関する注意事項要約: 1. ...

MySQLのマスタースレーブレプリケーションと読み取り書き込み分離を理解するための記事

目次導入1. MySQL マスタースレーブレプリケーション1. MySQLレプリケーションタイプ2....

Nginx プロセス スケジューリングの問題の詳細な説明

Nginx は、マスター プロセス (MasterProcess) と、同じ数のホスト CPU コア...

Docker swarm を使用して Nebula Graph クラスターを迅速にデプロイする方法のチュートリアル

1. はじめにこの記事では、Docker Swarm を使用して Nebula Graph クラスタ...

Vue3 ベースのスクリプト設定構文 $refs の使用

目次1. Vue2 構文2. Vue3の使用1. コンポーネントのref値を設定する2. コンポーネ...

Mysqlはマスタースレーブ構成とマルチマスターマルチスレーブ構成を実装します

現在シミュレーションしているのは、マスター スレーブ システム (ホスト 1 台とスレーブ 1 台)...

Vue3 を使用してポップアップ コンポーネントをカプセル化するのは簡単ですか?

目次最初に要約: 🌲🌲 序文: 🍬🍬公開🍬🍬 🍬🍬グローバル🍬🍬 🍬🍬ボールボックス🍬🍬 🎉🎉🎉結論...

MYSQL SERVER のログファイルを縮小する方法

トランザクション ログには、関連するデータベースに対する操作が記録され、データベースの回復に関連する...

JavaScriptはクリックするとランダムなグラフィックを生成します

この記事では、クリックするとランダムグラフィックの生成を実現するJavaScriptの具体的なコード...