第1段階モジュール1Mybatisカスタムフレームワークノート

記事のディレクトリ


序文

記事の内容の出力ソース:Lagou Education Java High Salary TrainingCamp。P7コース
この記事は、学習コースの放課後のメモの一部です。


プロジェクトアドレス

プロジェクトコード:
リンク:https
://pan.baidu.com/s/1pdtE7NkQb1SHQo9RnfSOTw抽出コード:sc4m

コードクラウドアドレス:https//gitee.com/nie_jian_ming/njm_all_homework/tree/master/%E7%AC%AC%E4%B8%80%E9%98%B6%E6%AE%B5.%E6%A8% A1%E5%9D%97%E4%B8%80.mybatis%E4%BD%9C%E4%B8%9A

1.従来のJDBCの問題とカスタムフレームワークソリューション

質問:
1。データベース接続の頻繁な作成と解放は、システムリソースの浪費を引き起こし、システムのパフォーマンスに影響を与えます。
2. sqlステートメント、パラメーターの受け渡し、および分析結果セットはすべてハードコーディングされています。SQLの変更にはJavaコードの変更が必要であるため、コードの保守が困難になります。
解決策:
1。データベース接続プールを使用して接続リソースを初期化し、データベース接続を頻繁に作成および解放する問題を解決します。
2. sqlステートメントをxml構成ファイルに抽出し、リフレクション、イントロスペクション、およびその他の基盤となるテクノロジーを使用して、エンティティーとテーブルを属性とフィールドに自動的にマップし、リフレクションを使用してパラメーターを設定し、イントロスペクションを使用して結果セットパッケージを返します。
関連するデザインパターン:
ビルダーデザインパターン、手動パターン(セッションファクトリ)、プロキシモード(Daoインターフェイスのプロキシオブジェクトを生成するJDK動的プロキシ)

2.カスタマイズされた永続性レイヤーフレームワークの設計アイデア

2.1。ユーザー側(プロジェクト):カスタム永続層フレームワークのjarパッケージを導入します

  • 構成情報の2つの部分を提供します:データベース構成情報、SQL構成情報(SQLステートメント、パラメーター・タイプ、戻り値タイプ)
  • 構成ファイルを使用して、構成情報の次の2つの部分を提供します
    。1.sqlMapConfig.xml:データベース構成情報を格納し、mapper.xmlをインポートします。
    2.mapper.xml:SQL構成情報を保存します。

2.2。カスタム永続層フレームワーク自体(エンジニアリング):本質はJDBCをカプセル化することです

2.2.1。構成ファイルを読み取ります。

  • 構成ファイルのパスに従って構成ファイルをバイト入力ストリームにロードするクラスを作成し、それをメモリーに保管します。
    実装手順:クラスの作成Resources、loadメソッド:InputSteam getResourceAsSteam(String path)
    読み取られた構成情報は、操作が簡単ではないストリームの形式でメモリに格納されます。ここでは、2つのjavaBean(コンテナオブジェクト)が作成されます。オブジェクト指向の考え方の場合:構成ファイルの解析済みコンテンツを保存します。これは、後でアクセスする場合にも便利です。
    実装手順:2つの構成クラスを作成します
    構成:コア構成クラス:sqlMapConfig.xmlによって解析されたコンテンツを保存し、データベースの基本情報を保存します、Map <のみID、マッパー>一意のID:名前空間+ "。" + id
    MappedStatement:マッピング構成クラス:mapper.xmlによって解析されたコンテンツを格納し、sqlステートメント、ステートメントタイプ、入力パラメーターjavaタイプ、出力パラメーターjavaタイプを格納します。

2.2.2。構成ファイルの解析:ここではdom4jを使用していますが、他のファイルも使用できます。

実装手順:
SqlSessionFactoryBuilderクラスを作成してから、メソッドbuild(InputSteam in)を作成してセッションファクトリをビルドします。
buildメソッドには2つのことが実装されてい
ます。1。dom4jを使用して構成ファイルを解析し、解析されたコンテンツをコンテナーオブジェクトにカプセル化します。
2. SqlSessionFactory(ファクトリモード)オブジェクトを作成し、sqlSessionセッションオブジェクトを生成します

2.2.3.SqlSessionFactoryインターフェイスと実装クラスDefaultSqlSessionFactoryを作成します。

次に、開始と終了の原則に基づいて、SqlSessionFactoryインターフェイスと実装クラスDefaultSqlSessionFactoryを作成します。sqlSessionを生成するためのメソッドを記述します。
メソッド:openSession()//
sqlSessionインターフェースの実装クラスインスタンスオブジェクトを取得するJDBCのCRUDメソッドをカプセル化するためにsqlSessionインターフェースと実装クラスDefaultSqlSessionを作成することを忘れないでください。

2.2.4。Executorインターフェイスと実装クラスSimpleExecutor実装クラスを作成し、JDBCコードを実行するためのクエリメソッドを作成します。

メソッド:query(Configuration、MappedStatement、Object ... params);
構成:dom4jを使用してsqlMapConfig.xmlを解析する場合、解析されたコンテンツはさまざまな形式で構成オブジェクトにカプセル化され、データベース構成の情報は内部に保存されます。 。
MappedStatement:dom4jを使用してmapper.xmlを解析する場合、各タグのコンテンツは、SQL情報
オブジェクトを格納するmappedStatementオブジェクトに対応します... params:これは、ユーザーから渡されるパラメーターです。着用されますので、オブジェクト...可変パラメータ

3.genericTokenParserzhegタグパーサークラス

  1. このクラスは、パラメーター化された構築によってのみ作成できます
  2. genericTokenParserは、汎用トークンパーサークラスです。
  3. genericTokenParserが#{}プレースホルダーを解析するときは、tokenHandlerと連携する必要があります
  4. genericTokenParserの3つの構築パラメーターは、開始タグ、終了タグ、およびタグプロセッサーです。

4. sqlessionFactoyBuilder、sqlessionFactoy、sqlessionについて。

  1. sqlessionFactoyBuilderの最適なスコープはメソッドスコープであり、ローカルメソッド変数として定義できます。
  2. sqlessionFactoyの最適な範囲は、アプリケーションの範囲です。
  3. sqlessionの最適なスコープは、メソッドスコープまたはリクエストスコープです。

5.戻り値resultTypeと入力パラメーターparamterTypeについて

  1. resultTypeの戻り値の型は、完全なクラス名またはエイリアス、基本的なデータ型が許可されている、String、intなどです。
  2. resultTypeとresultMapのデータ構造は同じで、どちらもマップ構造です。
  3. mybatisでは、@ paramアノテーションを使用して複数のパラメーターエントリを実装することに加えて、Mapオブジェクトを使用して複数のパラメーター転送を実装することもできます。

6.mybatisのインターフェース開発仕様

  1. mapper.xmlの名前空間は、マッパーインターフェイスのクラスパスと同じです。
  2. マッパーインターフェイスのメソッド名は、mapper.xmlで定義されている各ステートメントのIDと同じです。
  3. マッパーインターフェイスメソッドの入力パラメータータイプは、mapper.xmlで定義されている各SQLのparameterTypeタイプと同じです。
  4. マッパーインターフェイスメソッドの出力パラメータータイプは、mapper.xmlで定義されている各SQLのresultTypeタイプと同じです。

7.mybatisのソースコードの内容について

  1. 関連するデザインパターンは、エージェントモデル、ビルダー(ビルダー/コンストラクター)モデル、ファクトリモデル、イテレーターモデルです。
  2. 機能アーキテクチャは、インターフェイスレイヤー、データ処理レイヤー、フレームワークサポートレイヤーの3つのレイヤーに分けることができます。
  3. statementHandler、paramterHandle、resultsHandlerなどのコアオブジェクトをインターセプトするプラグインをサポートします
  4. エグゼキュータは、SQLの生成とクエリキャッシュのメンテナンスを担当するエグゼキュータです。
  5. statementtHandlerは、jdbcステートメント(データベースSQLを実行するためのインターフェース)操作をカプセル化し、jdbcステートメントの操作を担当します。
  6. typeHandlerは、Javaデータ型とjdbcデータ型の間のマッピングと変換を担当します。
  7. sqlSourceは、ユーザーから渡されたparameterObjectに従ってSQLステートメントを動的に生成し、その情報をboundsql()オブジェクトにカプセル化する役割を果たします。

8.Mybatisの遅延読み込み、その実装原理は何ですか

Mybatisは遅延読み込みをサポートし、
関連付けオブジェクトとコレクションオブジェクトの遅延読み込みのみをサポートします。
関連付けは1対1を指し、コレクションは1対多のクエリを指します。
構成ファイルで、遅延読み込みを有効にするかどうかを構成できますlazyLoadingEnabled = true | false。

<settings>
    <!-- 打开延迟加载的开关 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 将积极加载改为消极加载,即延迟加载 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

実装原理
CGLIBを使用して、ターゲットオブジェクトのプロキシオブジェクトを作成します。ターゲットメソッドが呼び出されると、インターセプター
メソッドに入り、データが必要になると、SQLを呼び出してDBにクエリを実行します。
例:a.getB()。getName()が呼び出されると、インターセプターのinvoke()メソッドはa.getB()が
null値であることを検出し、事前に保存されたSQLを個別に送信して、関連するBオブジェクトをクエリします。 、およびクエリB。次にa.setB(b)を呼び出して、aのオブジェクトb属性に値を設定し、a.getB()。getName()メソッドの呼び出しを完了します。

9. Mybatis Executorの3つのタイプ、それらの違い

デフォルトはSimplExcutorSimpleExecutor
です。更新または選択が実行されるたびに、Statementオブジェクトが開かれ、Statementオブジェクトは使用後すぐに閉じられます。
ReuseExecutor:更新または選択を実行し、SQLをキーとして使用してStatementオブジェクトを検索し、存在する場合はそれを使用し、存在しない場合は作成します。使用後、Statementオブジェクトは閉じられませんが、のマップに配置されます。次の使用。
つまり、Statementオブジェクトを再利用することです。
BatchExecutor:更新を実行し(選択なし、JDBCバッチ処理は選択をサポートしません)、すべてのSQLをバッチaddBatch()に追加し、executeBatch()の統合実行を待ちます。複数のステートメントオブジェクトをキャッシュし、各ステートメントオブジェクトはaddBatch(の後)です。 )完了し、executeBatch()バッチ処理を1つずつ待ちます。
JDBCバッチ処理と同じです。

アクションの範囲: Executorのこれらの特性は、SqlSessionライフサイクルの範囲に厳密に制限されています。

Mybatis構成ファイルでは、デフォルトのExecutorTypeアクチュエータタイプを指定するか、ExecutorTypeタイプパラメータをDefaultSqlSessionFactoryのSqlSessionを作成するメソッドに手動で渡すことができます。

10. Mybatisのプライマリキャッシュとセカンダリキャッシュ(分散キャッシュは実装できません。サードパーティのキャッシュフレームワークが必要です)

1.ストレージ構造:第1レベルのキャッシュと第2レベルのキャッシュはすべてHashMap構造にキャッシュされます。
2.スコープ:第
1レベルのキャッシュはSqlSessionレベルで、スコープはSqlSessionです。Mybatisはデフォルトで第1レベルのキャッシュをオンにします。同じSqlSessionで、同じSqlがクエリされると、最初のクエリはcacheデータがない場合は、DBからクエリを実行し、HashMapにキャッシュします。2番目のクエリはキャッシュから直接フェッチされ、データがある場合は、DBをチェックせずに直接返されます。

第2レベルのキャッシュはマッパーレベルです。複数のSqlSessionが同じマッパーのSQLステートメントで動作します。複数のSqlSessionが第2レベルのキャッシュを共有できます。第2レベルのキャッシュはSqlSession全体にあります。
マッパーの下のSQLが初めて呼び出されると、情報が照会されます。照会された情報は、マッパーに対応する第2レベルのキャッシュ領域に格納されます。名前空間の下のマッパーマッピングファイルが2回呼び出されると、同じです。 SQLを使用して直接クエリを実行し、結果をセカンダリキャッシュにフェッチします。

3.無効化シナリオ:
第1レベルのキャッシュが追加、削除、または変更されると、キャッシュは無効化されます。
Springコンテナ管理では、各クエリが新しいsqlSessionを作成するため、分散環境でデータの不整合が発生することはありません。

第2レベルのキャッシュを使用する場合は、キャッシュタグを開き、selectでuseCache属性をtrueに追加し、更新および削除時にフラッシュキャッシュを手動で有効にしてキャッシュを更新する必要があります。useCache = falseが設定されている場合、第2レベルのキャッシュはオフになります。

11. Mybatisプラグインの動作原理と、プラグインの書き方

MyBatisで許可されているインターセプトのメソッドは次のとおりです
。Executor:(更新、クエリ、コミット、ロールバックなどのメソッド);
SQL構文ビルダーStatementHandler :(準備、パラメーター化、バッチ処理、クエリの更新などのメソッド);
パラメータープロセッサーParameterHandler :( getParameterObject、setParametersメソッド);
ResultSetHandler:(handleResultSets、handleOutputParametersなどのメソッド);

1.動作原理:
Mybatisは、Executor、StatementHandler、ParameterHandler、およびResultSetHandlerの4つのインターフェイスのプラグインを記述できます。Mybatisは、JDKの動的プロキシを使用して、インターセプトが必要なインターフェイスのプロキシオブジェクトを生成し、インターセプトを実装します。インターフェイスのメソッドであるため、実行をインターセプトする必要がある場合インターフェイスメソッドの場合、インターセプトメソッドに入ります(AOP思考)。
2.書き方: 1。Intercepror
インターフェースの実装クラスを書きます
2.プラグインの署名を設定し、mybatisにどのオブジェクトのどのメソッドをインターセプトするかを伝えます
3.最後に、プラグインをグローバル構成ファイルに登録します

例:

package com.njm.plugin;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Connection;
import java.util.Properties;


//插件签名,告诉mybatis当前插件拦截哪个对象的哪个方法
@Intercepts({  //这是个⼤花括号,也就这说这⾥可以定义多个@Signature,对多个地⽅拦截,都⽤这个拦截器
         /*
        type:表示要拦截的核心(目标)对象,拦截哪个接⼝,StatementHandler是一个sql语句构建器,用来完成sql语句预处理
        method:表示要要拦截的方法,prepare是StatementHandler里的sql预编译方法
        args:表示要拦截方法的参数,按方法里的参数顺序写,可能方法有重载,所以要通过⽅法名和⼊参来确定唯⼀。
         */
        @Signature(type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class,Integer.class})
})
public class MyPlugin implements Interceptor {

    //截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行intercept方法
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        /*
         * 插件的主要功能:在执行目标方法之前,可以对sql进行修改已完成特定的功能
         * 例如增加分页功能,实际就是给sql语句添加limit;还有其他等等操作都可以
         * */
        System.out.println("对方法进行了增强。。。。。。。");
        return invocation.proceed(); //invocation.proceed():原方法执行并返回值
    }

    //主要为了把当前的拦截器生成代理存到拦截器链中,包装目标对象,为目标对象创建代理对象
    @Override
    public Object plugin(Object target) {
        //target:被拦截的目标对象,this:表示当前自定义的插件实现类,当前拦截器,也就是现在这个类,
        //wrap方法利用mybatis封装的方法为目标对象创建代理对象(没有拦截的对象会直接返回,不会创建代理对象)
        Object wrap = Plugin.wrap(target, this);
        return wrap;
    }

    //获取配置文件的参数,就是获取插件在配置文件中配置的参数值
    //插件初始化的时候调⽤,也只调⽤⼀次,插件配置的属性从这⾥设置进来
    @Override
    public void setProperties(Properties properties) {
        System.out.println("获取到的配置文件的参数是:"+properties);
    }
}

プラグインはグローバル設定ファイルに登録されています

 <!--配置自定义插件类
        interceptor:配置类的路径
        property:配置的参数-->
    <plugins>
      <!--这个是我自定义的插件-->
		 <plugin interceptor="com.njm.plugin.MyPlugin">
		 	<property name="name" value="tom"/>
		 </plugin>
		 
        <!--这是分页插件,上面的是我自定义的插件-->
<!--        <plugin interceptor="com.github.pagehelper.PageHelper">-->
            <!--指定方言-->
<!--            <property name="dialect" value="mysql"/>-->
<!--        </plugin>-->

    </plugins>

おすすめ

転載: blog.csdn.net/weixin_39417423/article/details/108332236