2016-06-17 2 views
4

MyBatis XML에 정수 목록을 전달하여 MySQL 쿼리의 in 절에 사용하려면 어떻게해야합니까?MyBatis 'IN'절의 목록

파일의 쿼리와 함께 Java 7, MySQL 5.6 DB 및 MyBatis 3.0.4를 사용하고 있습니다.

현재이 정수 목록을 문자열로 변환하고 문자열 대체 (${} 연산자)를 사용하여 'IN'절에 값을 넣습니다. 예상대로 작동하지만이 방법은 매개 변수를 Injection에 취약하게 만듭니다 .

나는 <foreach> 요소를 사용해 보았지만 어떤 속성을 지정해야 할지를 알 수 없습니다.

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); 
} 

매퍼 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] 
+1

나는 그런 [**이 한 ** (http://stackoverflow.com/questions/18388936/how-to-iterate-through-과 같은 몇 가지 관련 질문을 확인하신 후 쉽게해야한다 hashmap-in-mybatis-foreach? lq = 1), foreach 속성을 지정하는 방법을 알 수는 없습니다. 다음은 [** dtd **] (http://mybatis.org/dtd/mybatis-3-mapper.dtd)의 샘플입니다. '! bub

+1

당신의 스트립퍼 아이디가 null 또는 비어 있습니까? – Blank

+0

아니요, strippperIds가 null/empty가 아니며 값이 있습니다. – bub

답변

3

목록과 함께 사용되는 경우 foreach 태그 내에서 item 속성으로 지정된 값을 사용해야합니다. 다음과 같이 사용하십시오 :

<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 문에 액세스 할 수 있습니다.

샘플 콩 :

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; 
    }  
} 

구현에서 : 매퍼 XML의

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); 

:

<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> 

좋은 질문 당신은 일반적으로 INSERT/UPDATE 문이를 사용합니다 BTW :)

1

귀하의 XML은 다음과 같이해야한다 :

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

지도를 사용

(또는 Map.Entry 객체의 컬렉션) 인덱스는 키 객체가되고 항목은 값 객체가됩니다.

자세한 내용은 here을 참조하십시오. 속성에 대한 확실한 이해를 갖게됩니다.

0

입력 사항이지도입니다. 따라서 stripperIds를 직접 호출하기 전에 입력에서 stripperIds를 해결해야합니다.

1

주석을 사용하면

@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);