10
votes

Comment utiliser SELECT dans la clause de JDBCTTEMPLET?

Ceci est ma première expérience avec jdbCtemplates et j'ai couru dans un cas où je dois utiliser une requête qui ressemble à ceci: xxx

Comment puis-je faire ça? J'ai déjà essayé de transmettre une valeur de liste / de matrice, mais cela n'a pas fait l'affaire, je reçois une exception. Mon code actuel ressemble à ceci: xxx

Documentation de printemps indique qu'il n'y a aucun moyen de le faire en plus de générer le nombre requis de"? " placements pour correspondre à la taille de la liste des paramètres. Y a-t-il une solution de contournement?


2 commentaires

La clause SQL IN n'accepte pas une seule variable pour représenter une liste de valeurs - aucune base de données ne fait pas, sans utiliser SQL dynamique.


J'avais peur que ce soit le cas ... Je veux dire que choisir est aussi vieux que SQL lui-même, WTF !! Je suis dérouté, il n'y a pas de soutien pour cela.


4 Réponses :


3
votes

Je ne pense pas que vous puissiez faire cela comme un seul '?'. Ce n'est rien à voir avec les modèles Spring JDBC, c'est Core SQL.

Vous devrez construire un (?,?,?) Pour autant d'entre eux que nécessaire.


2 commentaires

Il y a une solution de contournement pour cela qui ne vous oblige pas à ajouter de manière dynamique "?" placements vers la requête. Voir ma réponse ci-dessous.


incroyable que c'est la réponse acceptée. Voir la réponse upvote ci-dessous.



52
votes

Il y a une solution de contournement utilisant NamedParameterjdbctemplate au lieu de SimpleJDBCDaosupport , où vous pouvez faire quelque chose comme ceci: xxx

Ceci a une limitation potentiellement catastrophique concernant le nombre de paramètres que vous pouvez transmettre La liste qui dépend de la DB que vous utilisez.

espère que c'est utile ...


5 commentaires

Il fonctionne. La limitationcaropathique n'est pas produite dans mon projet.


@janwen La limitation concerne le nombre de paramètres que vous pouvez passer à une clause dans une clause, généralement la limite est de 1000, mais comme je l'ai dit, cela dépend de la DB. 1000 est assez élevé, donc sur la plupart des cas que vous devriez aller, c'est probablement votre cas


@Chepech est-ce que nous pouvons augmenter la limite?


Comment l'utiliser si je veux avoir une liste d'objets de classe personnalisée (avec Rowmapper) en conséquence?


@Vipin Vous le faites en deux étapes, dans la même transaction SQL (vraiment pas besoin de transaction, mais le même contexte - c'est-à-dire que vous ne fermez pas la connexion entre): faites d'abord une table temporaire et insérez vos valeurs. Ensuite, vous faites le choix avec une jointure unilatérale, par ex. joint gauche. BTW, vous devriez probablement supprimer la table TEMP dans un essai-enfin à nettoyer avant de laisser la connexion retourner dans une piscine de données ou similaire.



3
votes

Pour une liste longue (ex. Oracle a une limitation de 1000 éléments) Vous pouvez simplement le séparer à plus de sélection:

List<Long> listIds = Arrays.asList(1L, 2L, ..... , 10000L); // list with ids

String query = "select NOTE from NOTE where ID in (:listIds)";

List<String> noteListResult = new ArrayList<>();

int current = 0;
int iter = 100;

while (current < listIds.size()) {
    Map<String, List<Long>> noteIdsMap = Collections.singletonMap("listIds",
            listIds.subList(current, (current + iter > listIds.size()) ? listIds.size() : current + iter));

    List<String> noteListIter = namedParameterJdbcTemplate.queryForList(query, noteIdsMap, String.class);
    noteListResult.addAll(noteListIter);

    current += iter;
}

return noteListResult;


0 commentaires

0
votes

Veuillez essayer avec MapSQLParameTersource avec NamedParameterjdbCtemplate.

MapSqlParameterSource parameters = new MapSqlParameterSource();
    parameters.addValue("array", inputarray);
    NamedParameterJdbcTemplate jdbctemplate = new NamedParameterJdbcTemplate(
            this.jdbcTemplate.getDataSource());


0 commentaires