MyBatis 4:ダイナミックSQL

19727 ワード

動的SQLとは
MyBatisの強力な特性の1つは、通常、動的SQL能力です.JDBCや他の似たようなフレームワークを使用した経験がある場合は、条件がSQL文字列に直列に接続されていることがどんなに苦痛なのか、スペースを忘れたり、リストの最後のカンマを省略したりしてはいけないことを理解し、動的SQLはこの苦痛を徹底的に処理することができます.
通常、動的SQLを使用するのは独立した一部ではありません.MyBatisはもちろん、任意のマッピングされたSQL文で使用できる強力な動的SQL言語を使用してこの状況を改善します.
動的SQL要素はJSTLや他の類似のXMLベースのテキストプロセッサと似ています.MyBatisの以前のバージョンでは、多くの要素を理解する必要があります.MyBatis 3はそれらを大幅に向上させ、現在は元の半分未満の要素で動作することができます.MyBatisは機能の強いOGLLベースの式を採用して他の要素を除去します.
OK、紹介はここまで、次は動的SQLの勉強に入りましょう.
 
if
動的SQLで最も一般的なことは、where句の一部を含む条件です.たとえば、次のようになります.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student where studentId > #{studentId}
    <if test="studentName != null">
        and studentName = #{studentName};
    </if>
</select>

具体的なインプリメンテーションは書かれていません.もし私がこのように呼び出したら:
List<Student> list = StudentOperator.getInstance().selectInCondition(0, "Jack", 0, null);

クエリはstudentId>0、studentName=「Jack」のすべての学生情報です.呼び出し方法を変更すると、次のようになります.
List<Student> list = StudentOperator.getInstance().selectInCondition(0, null, 0, null);

では、studentId>0のすべての学生情報を検索します.
複数のwhere句も同じです.たとえば、次のようにします.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student where studentId > #{studentId}
    <if test="studentName != null and studentName != 'Jack' ">
        and studentName = #{studentName}
    </if>
    <if test="studentAge != 0">
        and studentAge = #{studentAge};
    </if>
</select>

やはり、ここにも「」があってはいけないので注意しましょう.
またtestでは文字列、整数型、浮動小数点型を判断し、大胆に判断条件を書くことができるでしょう.属性が複合タイプの場合、A.Bを使用して複合タイプの属性を取得して比較できます.
 
choose、when、otherwise
すべての応用条件を適用したくない場合がありますが、逆に多くの場合の1つを選択したい場合があります.Javaのswitch...case...と同様に、MyBasitはchoose要素を提供します.
上記の例では、両方のif判断が存在する可能性があります.次にchoose、when、otherを使用して修正します.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student where studentId > #{studentId}
    <choose>
        <when test="studentName != null">
            and studentName = #{studentName};
        </when>
        <when test="studentAge != 0">
            and studentAge = #{studentAge};
        </when>
        <otherwise>
            or 1 = 1;
        </otherwise>
    </choose>
</select>

2つのwhenは1つしか満足できず、満足しなければotherを歩く.注意ここにも「」と書いてはいけません.動的SQLも同じです.
 
trim、where、set
最初の例ではifの使い方を例にしましたが、この使い方には欠陥があります.動的SQLの外にwhere句が必要です.
どういう意味ですか.whereの後ろの句を動的に生成する必要がある場合が多いので、事前にwhereがあるのではなく、問題があります.例えば、次のようにします.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student where
    <if test="studentName != null and studentName != 'Jack' ">
        and studentName = #{studentName}
    </if>
    <if test="studentAge != 0">
        and studentAge = #{studentAge};
    </if>
</select>

すべての条件が一致しない場合、生成されるSQL文は次のようになります.
select * from student where

これにより、クエリーが失敗します.クエリー条件が1つだけ満たされていても問題があります.たとえばstudentNameを満たすとしましょう.生成されたSQL文は次のようになります.
select * from student where and studentName = #{studentName};

このクエリも失敗します.
解決策もあるが、巧みな方法はwhere 1=1の方法である.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student where 1 = 1
    <if test="studentName != null and studentName != 'Jack' ">
        and studentName = #{studentName}
    </if>
    <if test="studentAge != 0">
        and studentAge = #{studentAge};
    </if>
</select>

「1=1」は永遠に満たされるので、whereにtrueを追加することに相当します.このとき、動的SQLがどのようなwhereを生成するかは、条件が何であるかを判断します.
もう1つの解決策はMyBatisの簡単な処理方法を利用することであり、90%の場合に役立ちます.使用できない場所では、カスタムで処理できます.簡単な変更を加えると、すべてのことが順調に進みます.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student
    <where>
        <if test="studentName != null and studentName != 'Jack' ">
            and studentName = #{studentName}
        </if>
        <if test="studentAge != 0">
            and studentAge = #{studentAge};
        </if>
    </where>
</select>

where要素は、含まれたタグによって任意の内容が返されると、whereのみが挿入されることを知っている.また、「and」または「or」で始まる内容であれば、whereをスキップして挿入しません.
where要素が目的のものを作成していない場合は、trim要素を使用してカスタマイズできます.たとえば、where要素と等しいtrim要素は、次のとおりです.
<trim prefix="WHERE" prefixOverrides="AND |OR "></trim>

次のようになります.
<select id="selectInCondition" parameterType="student" resultType="student">
    select * from student
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
        <if test="studentName != null and studentName != 'Jack' ">
            and studentName = #{studentName}
        </if>
        <if test="studentAge != 0">
            and studentAge = #{studentAge};
        </if>
    </trim>
</select>

特に、prefixOverridesの空白も重要です.
最後の小さな内容で、動的更新文に似たソリューションはsetです.set要素は、更新を必要としないカラムを含まずに更新を動的に含むために使用することができる.例:
<update id="updateStudentAgeById" parameterType="Student">
    <!--update student set studentAge = #{studentAge} where 
        studentId = #{studentId}; -->
    update student 
    <set>
        <if test="studentAge != 0">studentAge = #{studentAge}</if>
    </set>
    where studentId = #{studentId}
</update>

対照的に、注釈は元のupdate文で、注釈がないのは動的SQLを加えた後の文です.
ここで、set要素はsetキーワードを動的に前置きし、関係のないカンマも消去します.ここと対等なtrim要素に興味がある場合は、次のように見えます.
<trim prefix="SET" prefixOverrides=","></trim>

この場合、接尾辞を添付し、接頭辞も添付します.
 
foreach
もう1つの動的SQL共通の必要な操作は、通常in条件で構築される集合を反復する.例えば(上記の例はすべて私が自分のパソコンで走った例で、この例はMyBatisの公式ドキュメントの内容を直接コピーしました):
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT * FROM POST P WHERE ID in
  <foreach item="item" index="index" collection="list"
    open="(" separator="," close=")">
    #{item}
  </foreach>
</select>

foreachは非常に強力で、要素内で使用できる集合を指定し、集合項目とインデックス変数を宣言することができます.また、文字列を開いたり閉じたりして、反復間に区切り記号を配置することもできます.この要素はインテリジェントで、偶然に余分な区切り文字を付加しません.