web-dev-qa-db-fra.com

Listes dans la clause 'IN' de MyBatis

Comment puis-je passer une liste entière à MyBatis XML, à utiliser dans une clause in dans ma requête MySQL?

J'utilise Java 7, MySQL 5.6 DB et MyBatis 3.0.4 avec des requêtes dans un fichier mapper-xml.

Actuellement, je convertis cette liste d'entiers en chaîne et j'utilise la substitution de chaîne (opérateur ${}) pour placer les valeurs dans la clause 'IN'. Cette méthode fonctionne normalement, mais rend le paramètre vulnérable à Injection.

J'ai essayé d'utiliser un élément <foreach>, mais je ne suis pas en mesure de déterminer les attributs à spécifier.

Voici un exemple de code Java:

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>

Je ne suis pas en mesure de déterminer quels attributs spécifier pour l'élément <foreach> - je continue à courir dans une exception NullPointerException pour la valeur située à # {index}.

Pouvez-vous m'aider à comprendre l'utilisation correcte de l'élément <foreach>?

Modifier :

@ 10086,

Ci-dessous la trace de la pile:

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]
6
bub

La valeur spécifiée par l'attribut item doit être utilisée à l'intérieur de la balise foreach, lorsqu'elle est utilisée avec des listes. Utilisez comme ci-dessous:

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

L'attribut d'index n'est pas obligatoire lors de l'utilisation d'une liste. Reportez-vous à la section documentation de MyBatis pour plus d'informations ou consultez la DTD - http://mybatis.org/dtd/mybatis-3-mapper.dtd pour plus d'informations sur les paramètres:

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

Les listes d’objets sont également accessibles dans foreach comme ci-dessous. Vous utiliserez généralement ceci pour les instructions INSERT/UPDATE:

Échantillon de haricot:

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

Dans votre implémentation:

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

Dans le mappeur 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>

Belle question BTW :)

4
N.M

Votre XML devrait être comme ça:

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

Lors de l'utilisation d'une carte (ou d'une collection d'objets Map.Entry), index sera l'objet clé et l'élément sera l'objet valeur.

Vous pouvez référencer ici pour les détails. Vous aurez une solide compréhension des attributs.

2
Sky

Utiliser l'annotation devrait être plus facile 

@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);
1
Tiago Medici

votre entrée est une carte. vous devez donc résoudre stripperIds de l’entrée avant d’appeler directement stripperIds. 

0
starzmasta