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]
リストで使用する場合は、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>
ところで素敵な質問:)
アノテーションを使用する方が簡単です
@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);
あなたのxmlは次のようになります:
<foreach item="item" index="index" collection="stripperIds" open="(" separator="," close=")">
#{item}
</foreach>
Map(またはMap.Entryオブジェクトのコレクション)を使用する場合、インデックスはキーオブジェクトになり、アイテムは値オブジェクトになります。
詳細は here を参照してください。あなたは属性についてしっかりと理解するでしょう。
入力はマップです。そのため、stripperIdsを直接呼び出す前に、入力からstripperIdsを解決する必要があります。