web-dev-qa-db-fra.com

Comment passer une clause tableau entier à IN dans MyBatis

Il y a une requête dans mon Mybatis contenant une clause IN qui est fondamentalement un ensemble d'identifiants (entiers)

Je suis maintenant coincé sur la façon de passer un tableau Integer à cette clause IN afin qu'il récupère les enregistrements appropriés.Essayé en passant une chaîne contenant les ID à la clause IN, mais cela n'a pas fonctionné comme prévu.

Exemple de code ci-dessous

Méthode Mybatis à l'aide d'annotations

@Select(SEL_QUERY)
    @Results(value = {@Result(property="id",column="ID")})
    List<Integer> getIds(@Param("usrIds") Integer[] usrIds);

Requete

select distinct ID from table a where a.id in ( #{usrIds} )

Appel de méthode

Integer[] arr = new Integer[2];
arr[0] = 1;
arr[1] = 2;

mapper.getIds(arr)

Cela ne fonctionne pas, Mybatis génère une erreur lorsque j'appelle la méthode mapper

Toutes suggestions s'il vous plaît

24
Vivek

Le Guide de l'utilisateur myBatis sur SQL dynamique contient un exemple sur la façon d'utiliser une boucle foreach pour créer la chaîne de requête, qui fonctionne pour les listes et les tableaux.

Avant la version 3.2, vous deviez utiliser la configuration xml pour utiliser SQL dynamique, avec les versions plus récentes, il devrait également être possible d'utiliser SQL dynamique dans les annotations .

<select id="selectPostIn" resultType="domain.blog.Post">
    SELECT *
    FROM POST P
    WHERE ID in
    <foreach item="item" index="index" collection="list"
             open="(" separator="," close=")">
        #{item}
    </foreach>
</select>
33
Jörn Horstmann

OUI, vous pouvez le faire en utilisant des annotations.

Si vous utilisez postgresql , vous pouvez faire comme dans cet article .

Si vous utilisez MySQL essayez ces modifications dans votre exemple de code:

Méthode Mybatis à l'aide d'annotations

@Select(SEL_QUERY)
    @Results(value = {@Result(property="id",column="ID")})
    List<Integer> getIds(@Param("usrIds") String usrIds);

Requête (en utilisant MySQL)

select distinct ID from table a where FIND_IN_SET( a.id, #{usrIds}) <> 0

Appel de méthode

Integer[] arr = new Integer[2];
arr[0] = 1;
arr[1] = 2;

String usrIds= "";
for (int id : ids) {
    usrIds += id + ",";
}

mapper.getIds(usrIds) 
6
Italo Borssatto

Vous pouvez créer un nouveau gestionnaire de type et l'utiliser uniquement pour votre paramètre. La requête se changerait en:

SELECT ... WHERE FIND_IN_SET(id, #{usrIds, typeHandler=my.pkg.ListTypeHandler}) <> 0

Et le gestionnaire de type:

import Java.sql.PreparedStatement;
import Java.sql.SQLException;

import org.Apache.ibatis.type.JdbcType;
import org.Apache.ibatis.type.ObjectTypeHandler;

import com.google.common.base.Joiner;

public class ListTypeHandler extends ObjectTypeHandler {
    @Override
    public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setObject(i, Joiner.on(",").join((Iterable<?>) parameter), JdbcType.OTHER.TYPE_CODE);
    }
}
1
Italo Borssatto