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

推薦する

MySQLはテーブルデータを復元するためにfrmファイルとibdファイルを使用します

目次frm ファイルと ibd ファイルの紹介frm ファイル回復テーブル構造ibd ファイル回復テ...

MySQL InnoDB ReplicaSet の簡単な紹介

目次01 InnoDBレプリカセットの紹介02 InnoDBレプリカセットの制限03 導入前に知って...

検証コードケースのJavaScript実装

この記事では、検証コードの効果を実現するためのJavaScriptの具体的なコードを参考までに共有し...

crontab スケジュールされたタスクが実行されない理由の分析と解決

序文Linux のスケジュールされたタスクを実装する方法としては、cron、anacron、at な...

JS で async await をエレガントに使用する方法

目次jQuery の $.ajax Webpack時代の始まり約束について深く考えるネストをなくすj...

Nginx を使用してクロスドメイン Vue 開発環境を処理する方法

1. 需要正しい Cookie 配信と SSO テストを確実に実行できるように、ローカル テスト ド...

Webpack コンポーネントの使用状況統計を実装するための 50 行のコード

背景最近、リーダーからコンポーネント ライブラリを構築するように依頼があり、プロジェクトで現在使用さ...

MySQLデータベースのマスタースレーブレプリケーションの原理と機能の分析

目次1. データベースのマスター/スレーブ分類: 2. MySQL マスタースレーブの紹介3. マス...

反応自動構築ルーティングの実装

目次順序1. 集中ルーティング2. ファイルディレクトリ3. CompileRouterを作成する4...

Vue3は現在のルーティングアドレスを取得します

正解useRouterの使用: // ルーターパス: "/user/:uid" ...

mysqlreplicate を使って MySQL マスタースレーブを素早く構築する方法

導入mysql-utilities ツールセットは、DBA のツールボックスとも言えるさまざまなツー...

MySQL5.7 マスタースレーブ構成例の分析

MySQL5.7マスタースレーブ構成の実装方法、具体的な内容は次のとおりですインストール環境:マスタ...

MySQL実行計画の詳細な分析

序文前回の面接では、実行計画について質問されたとき、多くの人がそれが何なのか知りませんでした。実行計...

SQL インジェクションのある Web サイトを見つける方法 (必読)

方法 1: Google の詳細検索を使用します。たとえば、次に示すように.asp?id=9などの ...

MySQL トランザクションと分離レベルの基本原理の簡単な分析

目次序文1. 取引の基本原則の簡単な分析原子性:持続性分離:一貫性: 2. 分離レベルの基本原理の分...