web-dev-qa-db-ja.com

MyBatisの「IN」句のリスト

MyBatis XMLに整数リストを渡して、MySQLクエリのin句で使用するにはどうすればよいですか?

Java 7、MySQL 5.6 DBおよびMyBatis 3.0.4をmapper-xmlファイル内のクエリで使用しています。

現在、私はこの整数のリストを文字列に変換し、文字列置換(${}演算子)を使用して値を 'IN'句に入れています-期待どおりに機能しますが、このアプローチはパラメーターをインジェクションに対して脆弱にします。

<foreach>要素を使用してみましたが、指定する属性を特定できません。

以下はサンプルですJava code:

public List<Stripper> getStripperDetails(String club, List<Integer> stripperIds) {
        Map<String, Object> input = new HashMap<>();
        input.put("club", club);
        input.put("stripperIds", stripperIds);
        return stripClubMapper.getStripperDetails(input);
}

Mapper xml:

<select id="getStripperDetails" parameterType="Java.util.HashMap" resultMap="StripperMap">
    SELECT STRIPPER_ID, STAGE_NAME, REAL_NAME, CLUB FROM EXOTIC_DANCERS WHERE CLUB = #{club} AND STRIPPER_ID IN     
    <foreach item="item" index="index" collection="stripperIds" open="(" separator="," close=")">
        #{index}
    </foreach>
</select>

<foreach>要素に指定する属性を特定できません-#{index}の値でNullPointerExceptionが発生し続けます。

<foreach>要素の正しい使用法を理解していただけませんか?

編集:

@ 10086、

以下はスタックトレースです:

org.mybatis.spring.MyBatisSystemException: nested exception is org.Apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: Java.lang.NullPointerException
### The error may involve com.stripclub.mapper.stripClubMapper.getStripperDetails-Inline
### The error occurred while setting parameters
### Cause: Java.lang.NullPointerException
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.Java:67) ~[mybatis-spring-1.0.0-RC3.jar:1.0.0-RC3]
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.Java:345) ~[mybatis-spring-1.0.0-RC3.jar:1.0.0-RC3]
    at com.Sun.proxy.$Proxy208.selectList(Unknown Source) ~[na:na]
    at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.Java:193) ~[mybatis-spring-1.0.0-RC3.jar:1.0.0-RC3]
    at org.Apache.ibatis.binding.MapperMethod.executeForList(MapperMethod.Java:85) ~[mybatis-3.0.4.jar:3.0.4]
    at org.Apache.ibatis.binding.MapperMethod.execute(MapperMethod.Java:65) ~[mybatis-3.0.4.jar:3.0.4]
    at org.Apache.ibatis.binding.MapperProxy.invoke(MapperProxy.Java:38) ~[mybatis-3.0.4.jar:3.0.4]
    at com.Sun.proxy.$Proxy209.getTransactionIds(Unknown Source) ~[na:na]
8
bub

リストで使用する場合は、item属性で指定した値をforeachタグ内で使用する必要があります。以下のように使用してください:

    <foreach item="sId" collection="stripperIds" separator="," open="(" close=")">
        #{sId}
    </foreach>

リストを使用する場合、インデックス属性は必須ではありません。詳細については、MyBatisのドキュメントセクションを参照するか、DTDを確認してください。パラメータの詳細については、 http://mybatis.org/dtd/mybatis-3-mapper.dtd をご覧ください。

    <!ELEMENT foreach (#PCDATA | include | trim | where | set | foreach | choose | if | bind)*>
    <!ATTLIST foreach
    collection CDATA #REQUIRED
    item CDATA #IMPLIED
    index CDATA #IMPLIED
    open CDATA #IMPLIED
    close CDATA #IMPLIED
    separator CDATA #IMPLIED
    >

また、以下のようにforeachでオブジェクトのリストにアクセスできます。通常、これはINSERT/UPDATEステートメントに使用します。

サンプルBean:

public class StripperBean {

    public StripperBean(int stripperID, String stripperName, String realName) {
        this.stripperID = stripperID;
        this.stripperName = stripperName;
        this.realName = realName;
    }

    private int stripperID; 
    private String stripperName;
    private String realName;        

    public int getStripperID() {
        return stripperID;
    }
    public void setStripperID(int stripperID) {
        this.stripperID = stripperID;
    }
    public String getStripperName() {
        return stripperName;
    }
    public void setStripperName(String stripperName) {
        this.stripperName = stripperName;
    }
    public String getRealName() {
        return realName;
    }
    public void setRealName(String realName) {
        this.realName = realName;
    }       
}

あなたの実装では:

    Map<String, Object> input = new HashMap<>();
    input.put("club", club);
    List<StripperBean> strippers = new ArrayList<>();
    strippers.add(new StripperBean(1,"Ashley", "Jean Grey"));
    strippers.add(new StripperBean(2,"Candice","Diana Prince"));
    strippers.add(new StripperBean(3,"Cristal","Lara Croft"));        
    input.put("strippers", strippers);
    return stripClubMapper.saveStripperDetails(input);

マッパーxmlで:

    <insert id="saveStripperDetails">
        INSERT INTO EXOTIC_DANCERS (STRIPPER_ID, STAGE_NAME, REAL_NAME)
        VALUES
        <foreach item="stripper" collection="input" separator=",">
            (#{stripper.stripperID},
            #{stripper.stripperName},
            #{stripper.realName})
        </foreach>
    </select>

ところで素敵な質問:)

4
N.M

アノテーションを使用する方が簡単です

@Select({
        "<script>", "select", " * ", "FROM TABLE",
        "WHERE  CONDITION IN  " +
        "<foreach item='item' index='index' collection='list' open='(' separator=',' close=')'> #{item} </foreach>" +
        "</script>"  })
         @Results({ })
        List<POJO> selectByKeys(@Param("list") List<String> ids);
3
Tiago Medici

あなたのxmlは次のようになります:

<foreach item="item" index="index" collection="stripperIds" open="(" separator="," close=")">
    #{item}
</foreach>

Map(またはMap.Entryオブジェクトのコレクション)を使用する場合、インデックスはキーオブジェクトになり、アイテムは値オブジェクトになります。

詳細は here を参照してください。あなたは属性についてしっかりと理解するでしょう。

2
Sky

入力はマップです。そのため、stripperIdsを直接呼び出す前に、入力からstripperIdsを解決する必要があります。

0
starzmasta