web-dev-qa-db-ja.com

MyBatis 3でwhere_in句が空の場合、どうすればクエリをスキップできますか?

select * from users where id in ()

クエリは上に示されています。

<select id="getByIds" resultMap="BaseResultMap">
    SELECT
    <include refid="BaseColumnList"/>
    FROM users
    WHERE id IN
    <foreach item="id" collection="ids"
             open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

Param idsが空の場合、Mybatisは 'select * from users where id in'などのクエリを生成するBadSqlGrammarExceptionをスローします。

idsが空の場合、クエリをスキップして空のリストを返すにはどうすればよいですか?

10
wwulfric

Idが空の場合、クエリをスキップして空のリストを返すにはどうすればよいですか?

スキップクエリ(実行しない)には、Mybatisを呼び出さないでください。呼び出しコードは、idsが空かどうかを確認する必要があります。

return null == ids || ids.isEmpty() ? new ArrayList<User>() : session.select("getByIds", ids);

これはまさに質問で尋ねられたものです。

Mybatisで本当にこれを処理したい場合は、空の結果quicklyを返すために(スキップせずに)実行する必要があるため、生成されたクエリは有効でなければなりません。つまり、id = <!-- a value that will never exist in the table -->存在しない値を検索するために(無料で使い物にならない)フルスキャンを確実に含むことができるため。次に:

    WHERE 
    <choose>
        <when test="ids==null || ids.isEmpty()">
            1 = 0 <!-- a test returning false, to adapt depending on you DB vendor -->
        </when>
        <otherwise>
            id IN <foreach item="id" collection="ids" open="(" separator="," close=")">#{id}</foreach>
        </otherwise>
    </choose>

確認するもう1つのオプションは、インターセプターを使用してクエリを実行前に「キャンセル」することですが、これは間違いなく、ここで達成しなければならないことの過剰な複雑さです。

6
blackwizard

Javaコード関数

 List<ApiPriceChlogEntity> getApiAndDevPrice(@Param("apiKeys") List<String> currentApiKey, @Param("devKeys") List<String> currentDevKey, @Param("startDate") Date startDate);

マッパーファイル

<select id="getApiAndDevPrice"  resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM t_api_price_chlog tab1
<where>
    <if test="apiKeys.size() > 0">
      tab1.api_key IN
      <foreach collection="apiKeys" item="item" separator="," open="(" close=")" index="">
        #{item}
      </foreach>
    </if>
    <if test="devKeys.size() > 0">
      AND tab1.dev_key IN
      <foreach collection="devKeys" item="item" separator="," open="(" close=")" index="">
        #{item}
      </foreach>
    </if>

    <if test="startDate != null">
      AND tab1.change_date >= #{startDate}
    </if>
</where>

私はそれをテストしました、あなたを助けることを望みます。

2
Ordiy

テストを使用する:

<select id="getByIds" resultMap="BaseResultMap">
    SELECT
    <include refid="BaseColumnList"/>
    FROM users
<if test="ids!= null">
    WHERE id IN
    <foreach item="id" collection="ids"
             open="(" separator="," close=")">
        #{id}
    </foreach>
</if>
</select>
0
Thrash Bean