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 !
Votre changelog reprend les fonctionnalités que vous avez réalisé entre deux versions, ça tombe bien, votre historique git contient ces informations :) On va voir comment les extraire de git pour générer automatiquement un changelog exhaustif et fiable.
Le principe
Pour faciliter la maintenance de votre projet, il est d’usage d’avoir des commits parlants afin que tous les d...
Photo by Yancy Min on Unsplash
Contexte
Je suis développeur au quotidien et j'aime développer en dehors du travail également.
Parfois, il peut m’arriver de faire un kata entre midi et deux par exemple. J'aime bien du coup garder une trace de mon exerc...
On va prendre un cas concret: j’ai fait un commit et en relisant ma merge request, je me rend compte que certains fichiers ne devraient pas y être:
Dans mon cas c’est le fichier src/test/java/com/globaldashboard/unit/dependencies/domain/PomUrlTest.java
...
Dans une application Spring, sauf exceptions, les Beans sont proxifiés. En d’autres mots, on n'interagit pas directement avec eux et ce mécanisme est à la base de l’AOP.
Beaucoup de mécanismes s'appuient sur l’AOP (les Transactions par exemple) et conn...