Une gestion d’erreur de son API .Net automatique via ses exceptions
...
Sommaire
Avec Spring JDBCTemplate, on peut récupérer des résultats d’une requête SQL sous forme d’une liste d’objets à la manière d’un ORM.
On peut notamment utiliser BeanPropertyRowMapper, une implémentation de RowMapper fournie par Spring permettant de mapper automatiquement les lignes retournées vers nos entités.
On va voir dans cet article quelques exemples d’utilisation sur des cas concrets 🙂
Ce mapper est très pratique à utiliser car il permet de récupérer une liste d’objets simples sans aucune configuration. On va voir dans cette section comment il marche et ses limites:
Voici une entité très basique qui a 2 attributs: “id” et “name”:
public class KataEntity { private Long id; private String name; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Ma BDD a la configuration suivante:
CREATE TABLE KATA ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL );
Pour récupérer une liste de Kata, on peut utiliser la méthode query() de JDBCTemplate qui prend en paramètre une requête SQL et un RowMapper.
@Override public Collection<KataEntity> findAll() { return jdbcTemplate.query("SELECT id, name FROM kata", new BeanPropertyRowMapper<>(KataEntity.class)); }
On remarque que BeanPropertyRowMapper prend en paramètre la classe vers laquelle transformer les résultats.
Pour effectuer le mapping, il va prendre les résultats de la requête et appeler les setters correspondants.
Si on décortique l’exemple, je vais avoir un résultat de la forme:
ID | NAME |
1 | AperoTech |
Le mapper va déterminer les setters à utiliser suivant le nom des colonnes
id -> setId
name ->setName
Une fois fait, il va appeler le constructeur par défaut de la classe passée en paramètre (KataEntity dans mon cas) puis appeler les setters avec les données retournées.
En résumé, il fait donc
KataEntity kata = new KataEntity(); kata.setId(1) kata.setName("AperoTech")
Pour l’utiliser, il faut donc:
– Une classe qui a un constructeur par défaut.
– Une classe avec des setters qui s’appellent comme les en-têtes des résultats.
C’est pour cette raison que ce mapper est pratique mais pas performant (comme il fait de l’introspection).
Que faire si mes setters ne matchent pas le nom des colonnes ?
On peut utiliser des alias, si j’ai:
CREATE TABLE KATA ( id INT AUTO_INCREMENT PRIMARY KEY, label VARCHAR(255) NOT NULL );
et la même entité que précédemment, alors je peux faire:
@Override public Collection<KataEntity> findAll() { return jdbcTemplate.query("SELECT id, label as name FROM kata", new BeanPropertyRowMapper<>(KataEntity.class)); }
Si j’ai un objet qui a pour attributs d’autres objets ?
Spring JDBCTemplate est une surcouche au JDBC mais pas un ORM, vous ne pourrez pas faire ce mapping simplement. J’ai pu croiser plusieurs magouilles pour arriver à cette fin mais je vous conseille la façon standard: créer un rowMapper dédié et ne pas utiliser BeanPropertyRowMapper.
Imaginons que mon objet Kata défini précédemment ait en attribut un objet quelconque. Dans ma table, j’ai une colonne “objectId” avec l’id d’un objet. On devrait alors faire un Mapper:
public class KataEntityRowMapper implements RowMapper<KataEntity> { @Override public KataEntity mapRow(ResultSet rs, int rowNum) throws SQLException { KataEntity entity = new KataEntity(); entity.setId(rs.getLong("id")); entity.setName(rs.getString("name")); entity.customMethod(rs.getString("objectId")); return entity; } }
Puis l’appeler via
@Override public Collection<KataEntity> findAll() { return jdbcTemplate.query("SELECT id, label as name FROM kata", new KataEntityRowMapper()); }
Vous avez à présent toutes les cartes en main pour récupérer les résultats de vos requêtes dans des objets avec Spring JDBCTemplate 🙂 Le code des mappers peut paraître boilerplate (et à mon sens il l’est) mais il ne faut pas oublier qu’on utilise une surcouche à l’API JDBC et pas un ORM !
On va voir comment avoir en quelques minutes des assertions qui vont vérifier les endpoints de notre API avec des scénarios de ce genre: Feature: Create a new account As a visitor, I can create an account to access the game Scenario: A visitor c...
Depuis .NET 9, le le support d’OpenAPI est directement inclus dans .NET et ne passe plus par les librairies Swagger par défaut (plus d’info sur ce choix ici si jamais ça vous intéresse). De façons simplifiée, la librairie Swashbuckle.AspNetCore.Sw...
Description du problème Par défaut, il n’est pas autorisé de faire des requêtes entre une application qui est dans un domaine A vers une autre qui serait dans un domaine B (pour des raisons de sécurité, il y a plus de détails dans les sources). S...