MyBatis 動的 SQL の包括的な説明

MyBatis 動的 SQL の包括的な説明

序文

以前は、MySQL は静的 SQL を通じてクエリされていましたが、ビジネスが複雑な場合は引用符の問題や余分なスペースが発生し、SQL コードが間違ってしまいます。そのため、この問題を解決するために動的 SQL があります。

Mybatis フレームワークの動的 SQL テクノロジは、特定の条件に従って SQL 文を動的に組み立てる機能です。その目的は、SQL 文の文字列を連結する際の問題点を解決することです。これはタグを通じて行われます。

動的SQL

1. まずモジュールのディレクトリ構造を見てみましょう

クラスパス内のリソースの下のマッパー パッケージに sql.xml ファイルを作成します (共通性の抽出)

2. 物理モデリングと論理モデリング

ここでは物理モデリングの手順は省略されており、データベース テーブルは pojo クラスに対応している必要があります。

パッケージ pojo;

lombok.AllArgsConstructor をインポートします。
lombok.Data をインポートします。
lombok.NoArgsConstructor をインポートします。

@データ
@AllArgsコンストラクタ
@NoArgsコンストラクタ
パブリッククラスEmployee {
    プライベート整数 empId;
    プライベート文字列empName;
    プライベートダブルempSalary;

}

3. 依存関係の導入

以前の log4j をクラスパス リソースにコピーします。また、依存関係を導入した後の pom.xml ファイルは次のようになります。

<?xml バージョン="1.0" エンコーディング="UTF-8"?>
<プロジェクト xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <モデルバージョン>4.0.0</モデルバージョン>

    <グループID>org.example</グループID>
    <artifactId>day03-mybatis02-ダイナミック</artifactId>
    <バージョン>1.0-SNAPSHOT</バージョン>
    <packaging>jar</packaging>

    <依存関係>
        <依存関係>
            <groupId>org.projectlombok</groupId>
            <artifactId>ロンボク</artifactId>
            <バージョン>1.18.8</バージョン>
            <scope>提供</scope>
        </依存関係>

        <!-- Mybatis コア -->
        <依存関係>
            <グループID>org.mybatis</グループID>
            <artifactId>マイバティス</artifactId>
            <バージョン>3.5.7</バージョン>
        </依存関係>

        <!-- junit テスト -->
        <依存関係>
            <groupId>ジュニット</groupId>
            <artifactId>junit</artifactId>
            <バージョン>4.12</バージョン>
            <scope>テスト</scope>
        </依存関係>

        <!-- MySQL ドライバー -->
        <依存関係>
            <グループID>mysql</グループID>
            <artifactId>mysql-コネクタ-java</artifactId>
            <バージョン>5.1.3</バージョン>
            <scope>ランタイム</scope>
        </依存関係>

        <!-- log4j ログ -->
        <依存関係>
            <グループID>log4j</グループID>
            <アーティファクトID>log4j</アーティファクトID>
            <バージョン>1.2.17</バージョン>
        </依存関係>
    </依存関係>

</プロジェクト>

4. グローバル設定ファイル

<?xml バージョン="1.0" エンコーディング="UTF-8" ?>
<!DOCTYPE 設定
        パブリック "-//mybatis.org//DTD 構成 3.0//EN"
        「http://mybatis.org/dtd/mybatis-3-config.dtd」を参照してください。
<構成>
    <!--キャメルケースマッピング-->
    <設定>
        <設定名="mapUnderscoreToCamelCase" 値="true"/>
    </設定>
    <!-- 型エイリアスのマッピング -->
    <タイプエイリアス>
        <パッケージ名="pojo"/>
    </typeAliases>
    <!--環境設定-->
    <環境デフォルト="dev">
        <環境id="dev">
            <トランザクションマネージャタイプ="JDBC"></トランザクションマネージャ>
            <データソースタイプ="プール済み">
                <プロパティ名="ユーザー名" 値="ルート"/>
                <プロパティ名="パスワード" 値="888888"/>
                <プロパティ名="url" 値="jdbc:mysql://localhost:3306/mybatis-example"/>
                <プロパティ名="driver" 値="com.mysql.jdbc.Driver"/>
            </データソース>
                
        </環境>
    </環境>
    <!--パス マッピング-->
    <マッパー>
        <mapper リソース="mapper/sql.xml"/>
        <パッケージ名="マッパー"/>
    </マッパー>
</構成>

注: キャメルケース マッピング、エイリアス マッピング、パス マッピング、パス マッピングがあります。前回と異なるのは、ここでは SQL ステートメントの共通性抽出を行っているため、SQL パス マッピング<mapper resource="mapper/sql.xml"/>を追加する必要があることです。

5. SQL共通抽出ファイル

クラスパス リソースの下のパッケージ マッパーに sql.xml を作成します (sql はマッピング ファイルに書き込まれるため、また、マッピング ファイルでもあるため、マッパーの下に書き込む必要があります)。使用する必要がある場合は、マッピング パス ファイルでこの SQL ステートメントを使用する必要がある場所に<include refid="mapper.sql.mySelectSql"></include>を追加します。

<?xml バージョン="1.0" エンコーディング="UTF-8" ?>
<!DOCTYPE マッパー
        パブリック "-//mybatis.org//DTD マッパー 3.0//EN"
        「http://mybatis.org/dtd/mybatis-3-mapper.dtd」 を参照してください。
<マッパー名前空間="mapper.sql">

        <sql id="mySelectSql">
    t_emp から emp_id、emp_name、emp_salary を選択
</sql>


</マッパー>

共通抽出ファイルは未設定のままにすることもできます。この場合、マッピング ファイルで実行するステートメントを書き換えるだけで済みます。

6. マッパーインターフェース

全部で7つの方法があります

パッケージマッパー;

org.apache.ibatis.annotations.Param をインポートします。
pojo.Employee をインポートします。

java.util.List をインポートします。

パブリックインターフェースEmployeeMapper {

     // empId が従業員の empId より大きいすべての従業員を照会します。empId が null の場合は、すべての従業員を照会します。List<Employee> selectEmployeeListByEmpId(Integer empId);

    /**
     * 渡された empId よりも大きい empId を持ち、渡された empSalary よりも給与が大きい従業員のセットを照会します。渡された empId が null の場合、empId 条件は考慮されません。渡された empSalary が null の場合、empSalary 条件は考慮されません。 */
    リスト<従業員> selectEmployeeListByEmpIdAndEmpSalary(@Param("empId") Integer empId, @Param("empSalary") Double empSalary);

    /**
     * empId に基づいて従業員情報を更新します。値が null の場合、このフィールドは更新されません。 */
    void updateEmployee(従業員 employee);

    /**
     * emp_id に基づいて従業員情報を照会します。0<emp_id<6 の場合、emp_id が 6 より大きいすべての従業員を照会します。emp_id が 6 より大きい場合は、emp_id が 6 未満のすべての従業員を照会します。 * それ以外の場合は、すべての従業員情報を照会します。 */
    リスト<従業員> selectEmployeeList(Integer empId);

    /**
     * 従業員情報を追加 */
    void insertEmployee(従業員 employee);

    /**
     * 従業員コレクションを一括で追加 */
    void insertEmployeeList(@Param("employeeList") List<Employee> employeeList);

    /**
     * 従業員IDセットに基づいて従業員セットを照会する*/
    リスト<従業員> selectEmployeeListByEmpIdList(リスト<整数> idList);
}

もし

目的: 従業員の empId より大きい empId を持つすべての従業員を照会します。empId が null の場合は、すべての従業員を照会します。

Dao インターフェースのメソッドは次のとおりです。
List<Employee> selectEmployeeListByEmpId(Integer empId);

静的SQL:

<select id="selectEmployeeListByEmpId" resultType="従業員">

    <include refid="mapper.sql.mySelectSql"></include> emp_id>#{empId} の場合

</選択>

動的SQL:

<select id="selectEmployeeListByEmpId" resultType="従業員">
     <include refid="mapper.sql.mySelectSql"></include>
     <if テスト="empId != null">
         emp_id>#{empId} の場合
     </if>
 </選択>

<include refid="mapper.sql.mySelectSql"></include>抽出された SQL フラグメントを参照することを意味しますが、SQL ステートメントを直接記述することもできます。静的 SQL の場合、ID が null のときはクエリ結果は空になりますが、動的 SQL ではすべて見つけることができます。 if タグには、判断ステートメントとして機能するテスト属性名が含まれています。

どこ

ターゲット:

  • empId が渡された empId より大きく、給与が渡された empSalary より大きい従業員のセットを照会します。
  • 渡されたempIdがnullの場合、empId条件は考慮されません。
  • 渡された empSalary が null の場合、 empSalary の条件は考慮されません。

Dao インターフェース メソッド:

List<Employee> selectEmployeeListByEmpIdAndEmpSalary(@Param("empId") Integer empId, @Param("empSalary") Double empSalary);

if タグを使用した動的 SQL:

<select id="selectEmployeeListByEmpIdAndEmpSalary" resultType="従業員">
    <include refid="mapper.sql.mySelectSql"></include> ここで
   <if テスト="empId != null">
            従業員ID>#{従業員ID}
        </if>
        <if test="empSalary != null">
           emp_salary>#{empSalary} および emp_salary>#{empSalary}
        </if>

ここで、empSalary が空の場合、SQL ステートメントは select * from t_emp where emp_id >#{empId} ですが、empId が空の場合、SQL ステートメントは select * from t_emp where and emp_salary>#{empSalary} であることがわかります。明らかにこれは間違っており、if タグはここでは適用できません。そこで、where タグまたは trim タグを使用します。

where および if の動的 SQL:

<select id="selectEmployeeListByEmpIdAndEmpSalary" resultType="従業員">
    <include refid="mapper.sql.mySelectSql"></include>
   
    <どこ>
        <if テスト="empId != null">
            従業員ID>#{従業員ID}
        </if>
        <if test="empSalary != null">
           emp_salary>#{empSalary} および emp_salary>#{empSalary}
        </if>
    </どこ>
</選択>

where タグの役割:

  • 最初の条件の前にWHEREキーワードを自動的に追加します
  • 最初の条件(AND、ORなど)の前のコネクタを自動的に削除します。

トリム

トリムは構築するという意味ですが、実際には頭と尾を取り除くことを意味します。ここでは、上記の方法に従います。

トリムの動的SQL

<select id="selectEmployeeListByEmpIdAndEmpSalary" resultType="従業員">
    <include refid="mapper.sql.mySelectSql"></include>
    <trim prefix="WHERE" prefixOverrides="AND|OR">
        <if テスト="empId != null">
            従業員ID>#{従業員ID}
        </if>

        <if test="empSalary != null">
            AND emp_salary>#{empSalary}
        </if>
    </トリム>
</選択>

トリムタグ:

  • プレフィックス: 動的に追加するプレフィックスを指定します
  • サフィックス属性: 動的に追加するサフィックスを指定します
  • prefixOverrides: 複数の可能な値を「|」で区切って、動的に削除するプレフィックスを指定します。
  • suffixOverrides 属性: 複数の可能な値を「|」で区切って、動的に削除するサフィックスを指定します。

セット

目的: empId に基づいて従業員情報を更新します。値が null の場合、このフィールドを更新しないでください。

Dao インターフェース メソッド:
void updateEmployee(Employee employee);
この問題を解決するには、上記のトリム タグを使用しましょう。

トリムの動的 SQL:

<update id="updateEmployee">
    <トリム プレフィックス="set" prefixOverrides=",">
        <if test="empName!=null">
            従業員名=#{従業員名}
        </if>
        <if test="empSalary!=null">
            , emp_salary=#{empSalary}
        </if>
    </トリム>
    emp_id=#{empId} の場合
</更新>

セットの動的SQL

<update id="updateEmployee">
    t_emp を更新
     <設定>
         <if test="empName!=null">
             従業員名=#{従業員名}
         </if>
         <if test="empSalary!=null">
            , emp_salary=#{empSalary}
         </if>
     </set>

それは見ることができる

セットタグの機能:

  • 変更する最初のフィールドの前にSETキーワードを自動的に追加します
  • 変更する最初のフィールドの前のコネクタ (,) を削除します。

選択する、場合、それ以外の場合

ターゲット:

  • emp_id に基づいて従業員情報を照会します。0<emp_id<6 の場合は、それより大きい emp_id を持つすべての従業員を照会します。
  • emp_idが6より大きい場合は、emp_id未満のすべての従業員を照会します。
  • その他の場合は、すべての従業員情報を照会します

Dao インターフェース メソッド:
List<Employee> selectEmployeeList(Integer empId);

動的SQL

<select id="selectEmployeeList" resultType="従業員">
  
    <include refid="mapper.sql.mySelectSql"></include> ここで
    <選択>
    <!--&lt; は < --> のエスケープ文字です
        <test="empId>0 かつ empId&lt;6">の場合
            従業員ID>#{従業員ID}
        </いつ>
        <テスト時="empId>6">
            従業員ID&lt;#{従業員ID}
        </いつ>
        <それ以外の場合>
            1==1
        </そうでない場合>
    </選択>

</選択>

選択する、場合、それ以外の場合
if ... else if... else if ... else同等

  • when ステートメントの条件が満たされた場合、後続の when ステートメントは判断されません。
  • すべての when が true でない場合は、otherwise タグの内容が連結されます。

目標1: 従業員情報を一括で追加する

Dao インターフェース メソッド:

void insertEmployeeList(@Param("employeeList") List employeeList);

1. 動的SQL

<挿入id="従業員リストを挿入">
    t_emp(emp_name,emp_salary) 値に挿入
    <!--コレクションタグはリスト、コレクション、
    または、パラメータ名を自分で定義します @Param("employeeList") List<Employee> employeeList-->
    <foreach コレクション="従業員リスト" セパレーター="," 項目="emp">
        (#{emp.empName}、#{emp.empSalary})
    </foreach>
</挿入>

目標2: 複数のIDに基づいて複数の従業員情報を照会する

Dao インターフェース

List selectEmployeeListByEmpIdList(List idList);

2. 動的SQL

<select id="selectEmployeeListByEmpIdList" resultType="従業員">
    <include refid="mapper.sql.mySelectSql"></include>
     <foreach collection="コレクション" item="id" セパレーター="," open="emp_id が (" close=") 内にある">
         #{id}
     </foreach>
</選択>

バッチクエリ: foreach タグ

  1. collection 属性: トラバースするオブジェクトを示します。トラバースするパラメータが @Param アノテーションを使用して名前付けされている場合は、その名前を使用します。名前付けされていない場合は、List または collection を使用します。
  2. item 属性: トラバースされた要素を表します。この要素を使用して SQL 文を組み立てます。トラバースされた要素が POJO オブジェクトの場合は、#{トラバースされた要素.POJO 属性} を通じてデータを取得します。トラバースされた要素が単純なデータ型の場合は、#{トラバースされた要素} を使用してこの単純なデータ型を取得します。
  3. セパレータ属性: 走査される要素間のセパレータ
  4. open属性: 最初に走査される要素の前にプレフィックスを追加します
  5. close属性: 走査した最後の要素の後に接尾辞を追加します

テスト手順

mapper.EmployeeMapper をインポートします。
org.apache.ibatis.io.Resources をインポートします。
org.apache.ibatis.session.SqlSession をインポートします。
org.apache.ibatis.session.SqlSessionFactory をインポートします。
org.apache.ibatis.session.SqlSessionFactoryBuilder をインポートします。
org.junit.After をインポートします。
org.junit.Before をインポートします。
pojo.Employee をインポートします。

java.io.InputStream をインポートします。
java.util.ArrayList をインポートします。
java.util.List をインポートします。

パブリッククラステスト{
    プライベート EmployeeMapper employeeMapper;
    プライベート InputStream は、
    プライベート SqlSession sqlSession;
    @前に
    パブリック void init() 例外をスローします{
        //目標: EmployeeMapper インターフェースのプロキシ オブジェクトを取得し、それを使用して selectEmployee(1) メソッドを呼び出し、Employee オブジェクトを返します //1. グローバル構成ファイルをバイト入力ストリームに変換します is = Resources.getResourceAsStream("mybatisConfig.xml");
        //2. SqlSessionFactoryBuilder オブジェクトを作成する SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //3. ビルダー パターンを使用して SqlSessionFactory オブジェクトを作成します。SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        //4. ファクトリ モードを使用して SqlSession オブジェクトを作成します。sqlSession = sqlSessionFactory.openSession();
        //5. 動的プロキシ モードを使用して、EmployeeMapper のプロキシ オブジェクトを作成します。インターフェイス employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
    }


    @後
    パブリックvoid after()は例外をスローします{
        //トランザクションをコミットします!!!
        sqlSession.commit();
        //7. リソースを閉じる is.close();
        sqlSession を閉じます。
    }

    @org.junit.テスト
    パブリック void testSelectEmployeeListByEmpId(){
        System.out.println(employeeMapper.selectEmployeeListByEmpId(null));
    }

    @org.junit.テスト
    パブリック void testSelectEmployeeListByEmpIdAndEmpSalary(){
        System.out.println(employeeMapper.selectEmployeeListByEmpIdAndEmpSalary(2, 300d));
    }

    @org.junit.テスト
    パブリック void testUpdateEmployee(){
        従業員 employee = new Employee(3,"celia", 9000d);

        従業員マッパー。従業員を更新します。
    }

    @org.junit.テスト
    パブリック void testSelectEmployeeList(){
    System.out.println(employeeMapper.selectEmployeeList(7));
}

   @org.junit.テスト
   パブリック void testInsertEmployee(){
        employeeMapper.insertEmployee(新しい従業員(null、"tom",300d));
    }

    @org.junit.テスト
    パブリック void testInsertEmployeeList(){
        リスト<従業員> employeeList = 新しいArrayList<>();
        (int i = 11; i <= 20; i++) の場合 {
            従業員リストに新しい従業員を追加します(null、"aobama"+i、2000d))。
        }

        従業員マッパーに従業員リストを挿入します。

    }

    @org.junit.テスト
    パブリック void testSelectEmployeeListByEmpIdList(){
        リスト<Integer> idList = 新しいArrayList<>();
        idList.add(23);
        idList.add(33);
        idList.add(32);
        idList.add(21);
        idList.add(22);
        System.out.println(employeeMapper.selectEmployeeListByEmpIdList(idList));
    }


}

MyBatis 動的 SQL に関するこの記事はこれで終わりです。MyBatis 動的 SQL に関するその他の関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MyBatis は更新動的 SQL におけるカンマの問題を解決します
  • Mybatis 動的 SQL のテスト記述とルールの詳細な説明
  • Mybatis 動的 SQL でのテストの落とし穴のまとめ
  • Mybatis 動的 SQL サンプル コード
  • 1 時間で Mybatis エンティティ クラス名とマルチパラメータ動的 SQL を始めましょう
  • mybatisの動的SQLを紹介する記事

<<:  jQuery エディタ プラグイン tinyMCE の使い方

>>:  マウスをホバーすると画像が折りたたまれる効果を実現する CSS

推薦する

IDEA 構成の Tomcat 起動エラーの問題を解決する

異なるサーブレット パスを構成するときに、次の 2 つのエラーが発生しました。 java.lang....

Windows 7 で MySQL 8.0.16 をインストールして使用する場合、パスワードの変更と Navicat への接続に関する問題が発生する

MySQL のインストール時にいくつかの問題が発生しました。オンラインで見つけた回答は似たようなもの...

KVM 仮想マシンのオンライン ホット マイグレーションを実装する方法 (画像とテキスト)

1. KVM仮想マシンの移行方法と注意すべき点KVM 仮想マシンを移行する方法は 2 つあります。...

JavaScript のフラット配列をツリー構造に変換する例

目次バックグラウンドで10,000個のデータが失われた再帰法非再帰的方法要約するバックグラウンドで1...

uniappを使用してWeChatミニプログラムでEChartsを使用する方法

今日は、uniapp を使用して Echarts を統合し、マップ チャートを表示します。 mpvu...

MySql ビュー、トリガー、ストアド プロシージャに関する簡単な説明

ビュービューとは何ですか?ビューの役割は何ですか?ビューは仮想テーブルであり、データ自体を含まない論...

熟練デザイナーの7つの原則(2):色の使い方

<br />前回の記事:優秀なデザイナーの7つの原則(1):フォントデザイン 英語 原文...

親子コンポーネントの通信を解決するための3つのVueスロット

目次序文環境の準備カテゴリコンポーネントアプリのコンポーネント1. デフォルトスロット2. 名前付き...

データベースの水平セグメンテーションを実装するための2つのアイデア

導入インターネット アプリケーションの普及に伴い、膨大なデータの保存とアクセスがシステム設計における...

MySQLの自己接続と結合の詳細な理解

1. MySQL 自己接続MySQL では、情報を照会するときに自分自身に接続 (自己接続) する必...

Nginx リバース プロキシでセッション永続性を実装する 2 つの方法の詳細な説明

1. ip_hash: ip_hash は、送信元アドレス ハッシュ アルゴリズムを使用して、サーバ...

Vue でシンプルな無限ループスクロールアニメーションを実装する例

この記事では主に、Vue でシンプルな無限ループスクロールアニメーションを実装し、みんなで共有する例...

Debian 9 システムに MySQL データベースをインストールする方法

序文タイトルを見ると、誰もが「Debian 9 に MySQL をインストールするにはどうすればいい...

ディスクを破壊せずに Linux で dd コマンドを使用する方法

故障したストレージ ドライブからデータを救出する場合でも、アーカイブをリモート ストレージにバックア...

js を使用して数字推測ゲームを実装する

先週、先生が私に数字当てゲームをするちょっとした宿題を出しました。とても面白いと思ったので、適当に書...