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 🙂
I. BeanPropertyRowMapper
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.
II. Utiliser un RowMapper personnalisé
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());
}
Conclusion
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 !
source: https://imgflip.com/i/5f7ibr
Introduction
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).
Si vous avez un front qui tourne sur un serveur node (localhost:3000) et votre backend Spring sur (local...
Introduction
Si vous travaillez sur une API Spring au quotidien, vous pouvez trouver rébarbatif le fait de renseigner tous les codes HTTP correspondants aux différents cas d’erreur.
On peut les gérer cette façon:
@PostMapping
public ResponseEntit...
Image prise sur Windows Central
Historique
Pour cet article je vais faire un mini REX sur l’écosystème de Microsoft pour les développeurs.
J’ai commencé à travailler avec les technologies Microsoft vers 2016. Pour situer, Windows 10 devait avoir ...
Introduction
Vous l’avez sûrement remarqué, lorsque vous lancez votre application Spring Boot, vous avez une bannière de ce type qui s’affiche:
Il peut être intéressant de la changer, ne serait-ce que pour voir plus facilement dans les logs q...