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

推薦する

Nginx proxy_redirect の使用方法の詳細な説明

今日、Apache の nginx リバース プロキシを実行していたときに、ちょっとした問題に遭遇し...

HTML ウェブページハイパーリンクタグ

HTML ウェブ ページのハイパーリンク タグの学習チュートリアル リンク タグの属性 リンクは、ウ...

ウェブ開発者やデザイナーにとって欠かせないオンラインウェブツールとアプリケーション

これまでの記事で、フロントエンド開発者にとって必須のツール、スクリプト、リソースのコレクションを紹介...

C# は MySQL コマンドラインのバックアップとリカバリを実装します

MySQL データベースをバックアップするためのツールは多数あります。過去 2 日間で、C# を使用...

JavaScript で外部変数にアクセスするサブ関数の 3 つのソリューション

序文Web ページを作成するときに、次のような状況に遭遇することはよくあります。 <本文>...

MySQLデータベースのマスタースレーブ同期の実際のプロセスの詳細な説明

目次インストール環境の説明MySQLデータベースサービスをインストールするメインライブラリを構成する...

Linux の ufw ファイアウォールの紹介

Linux のufw (Uncomplicated Firewall) を見て、ファイアウォールに変...

Linux ユーザーとグループのコマンド例分析 [切り替え、ユーザーの追加、権限制御など]

この記事では、Linux のユーザーおよびグループのコマンドについて例を挙げて説明します。ご参考まで...

JavaScript ベースのパスワード ボックス検証情報の実装

この記事では、パスワードボックスの検証情報を実装するためのJavaScriptの具体的なコードを例と...

Windows 10 Home Edition に Docker をインストールする方法

最近、プロジェクトをアップグレードするために Docker を使用しました。これまで使用したことがな...

MySQL GTID の総合概要

目次01 GTIDの紹介02 GTIDの仕組み03 GTIDの利点と欠点04 テスト環境構築05 テ...

Flex プログラム Firefox で中国語を入力すると文字化けするバグ

Firefox の下位バージョンでは中国語の文字を入力できず、上位バージョンでは文字化けした文字が表...

iFrameは背景を覆うポップアップレイヤーとして使うのに最適です

最近、私は「ぶどうコレクション」というプロジェクトに取り組んでいます。簡単に言うと、Budou ペー...