web-dev-qa-db-fra.com

Méthode recommandée pour sélectionner des données à l'aide de Spring JdbcTemplate

Je veux savoir quelle est la meilleure pratique pour sélectionner des enregistrements dans une table. J'ai mentionné deux méthodes ci-dessous parmi lesquelles je veux savoir laquelle est la meilleure pratique pour sélectionner les données d'une table à l'aide de Spring JdbcTemplate .

Premier exemple

try {
    String sql = "SELECT id FROM tableName WHERE column_name = '" + coulmn value + "'";

    long id = jdbcTemplate.queryForObject(sql, Long.class);
} catch (Exception e) {
    if (log.isDebugEnabled()) {
        log.debug(e);
    }
}

Cela lève l'exception suivante:

Attendu 1 réel 0 comme

quand la table ne contient aucune donnée. Mon ami m'a dit que ce n'était pas la meilleure pratique pour sélectionner les données. Il a suggéré que le code mentionné ci-dessous soit la seule meilleure pratique pour sélectionner des données.

Deuxième exemple

try {
    String countQuery = "SELECT COUNT(id) FROM tableName";

    int count = jdbcTemplate.queryForInt(countQuery);
    if (count > 0) {
        String sql = "SELECT id FROM tableName WHERE column_name = '" + coulmn value + "'";

        long id = jdbcTemplate.queryForObject(sql, Long.class);
    }
} catch (Exception e) {
    if (log.isDebugEnabled()) {
        log.debug(e);
    }
}


J'ai hâte de connaître la bonne pratique ou toute autre pratique exemplaire.

18
Annamalai Thangaraj

La première méthode est sans aucun doute la meilleure pratique, car dans la deuxième méthode, vous frappez deux fois la base de données, alors que vous ne devriez y toucher qu’une fois. Cela peut causer des problèmes de performances.

Ce que vous devez faire, c'est intercepter l'exception EmptyResultDataAccessException puis renvoyer null. Les modèles Spring JDBC rejettent une exception EmptyResultDataAccessException / si elle ne trouve pas les données dans la base de données.

Votre code devrait ressembler à ceci. 

try {
     sql = "SELECT id FROM tableNmae WHERE column_name ='"+ coulmn value+ "'";
     id= jdbcTemplate.queryForObject(sql, Long.class);
} 
catch (EmptyResultDataAccessException e) {
   if(log.isDebugEnabled()){
       log.debug(e);
   }
   return null
}
16
Dhanush Gopinath

Meilleure façon d'utiliser ifNull dans la requête donc s'il y a null, vous obtenez 0.

sql = "SELECT ifNull(id,0) FROM tableName WHERE column_name ='"+ coulmn value+ "'";

De cette façon, vous pouvez obtenir par défaut 0 sinon votre identifiant

3
Vikram

Je suis confronté à un scénario similaire et j'ai trouvé une solution plus propre en utilisant ResultSetExtractor au lieu de RowMapper 

jdbcTemplate.query(DBConstants.GET_VENDOR_DOCUMENT, new Object[]{vendorid}, rs -> {

            if(rs.next()){
                DocumentPojo vendorDoc = new DocumentPojo();
                vendorDoc.setRegDocument(rs.getString("registrationdoc"));
                vendorDoc.setMsmeLetter(rs.getString("msmeletter"));
                vendorDoc.setProprietorshipDocument(rs.getString("propertiershipformat"));
                vendorDoc.setNeftDocument(rs.getString("neftdoc"));
                vendorDoc.setPanCardDocument(rs.getString("pancard"));
                vendorDoc.setCancelledChequeDoc(rs.getString("cheque"));
                return vendorDoc;
            }
            else {
                return null;
            }

    });

Si aucun résultat n'est trouvé dans la base de données, j'avais mis une condition if pour resultset et renvoyé une référence nulle. Donc, je n'ai pas eu besoin d'essayer d'attraper le code et de transmettre deux requêtes à la base de données. 

Le principal avantage de ResultSetExtractor (dans ce scénario) est avec ResultsetExtractor, vous devrez parcourir le jeu de résultats vous-même, par exemple en boucle while.

Plus de points peuvent être trouvés ici ici

2
Ankit

C'est le code source de la méthode queryForObject

@Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws 
DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.nullableSingleResult(results);
}

DataAccessUtils.nullableSingleResult

    @Nullable
public static <T> T nullableSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
    if (CollectionUtils.isEmpty(results)) {
        throw new EmptyResultDataAccessException(1);
    } else if (results.size() > 1) {
        throw new IncorrectResultSizeDataAccessException(1, results.size());
    } else {
        return results.iterator().next();
    }
}

je ne sais pas pourquoi ils jettent une exception sur une collection vide, c'est probablement juste un copier-coller de la méthode ci-dessus

    public static <T> T requiredSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
    if (CollectionUtils.isEmpty(results)) {
        throw new EmptyResultDataAccessException(1);
    } else if (results.size() > 1) {
        throw new IncorrectResultSizeDataAccessException(1, results.size());
    } else {
        return results.iterator().next();
    }
}

Un pas de plus au-dessus de la méthode qu’ils auraient dû utiliser 

    @Nullable
public static <T> T singleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
    if (CollectionUtils.isEmpty(results)) {
        return null;
    } else if (results.size() > 1) {
        throw new IncorrectResultSizeDataAccessException(1, results.size());
    } else {
        return results.iterator().next();
    }
}

NOW SOLUTION m'a aidé à: Étendre la classe JdbcTemlate (vous pouvez la construire avec DataSource injecté) Et remplacer la méthode queryForObject:

    @Nullable
public <T> T queryForObject(String sql, RowMapper<T> rowMapper) throws DataAccessException {
    List<T> results = this.query(sql, rowMapper);
    return DataAccessUtils.singleResult(results);
}

travaille maintenant avec votre implémentation N'oubliez pas de vérifier si cela fonctionne avec la mise à jour de version Spring (très à mon humble avis)

0
Anton Medvedev