Je veux afficher la liste des catégories sur ma page Jsp en utilisant spring mvc @modelAttribute.
Dans mon fichier mapper.xml est
<select id="selectAllCategories" resultMap="BaseResultMap">
select id, name from categories
</select>
Dans ma classe Mapper.Java, j'ai une méthode
List<Map<String, String>> selectAllCategories();
Je veux avoir une méthode comme celle-ci:
Map<Integer, String>`selectAllCategories();
au lieu de List<Map<>>
, est-ce possible?
Vous voulez obtenir un Map<Integer,String>
Où l'entier est le id
et la chaîne est le name
. S'il y avait 200 catégories dans votre tableau, vous voudriez 200 entrées dans votre carte, plutôt qu'une liste de 200 cartes.
MyBatis ne peut pas tout à fait faire cela, mais vous pouvez utiliser ses installations pour le faire. Je vois deux options.
Option 1:
Le premier n'est pas tout à fait ce que vous avez demandé mais mérite d'être montré. Il vous donne un Map<Integer,Category>
Où Category est un objet de domaine pour la table categories qui a id, nom (et éventuellement d'autres champs de la table categories). Une fois que vous avez créé l'objet de domaine Category, cela est assez facile à faire dans MyBatis en utilisant l'annotation @MapKey
:
@Select("SELECT id, name FROM categories")
@MapKey("id")
Map<Integer,Category> getAllCategories();
Dans votre code, vous feriez alors:
MyMapper mapper = session.getMapper(MyMapper.class);
Map<Integer,Category> m = mapper.getAllCategories();
Cela peut ou non fonctionner pour votre cas d'utilisation selon que vous pouvez extraire le nom en tant que propriété de l'objet Category.
Option 2:
Pour obtenir le Map<Integer,String>
Que vous avez demandé, la manière la plus simple que je connaisse est de créer une classe qui implémente l'interface MyBatis ResultHandler .
Votre ResultHandler utilisera la table de hachage par défaut de nom-colonne => valeur-colonne que MyBatis crée et crée une seule carte principale. Voici le code:
public class CategoryResultHandler implements ResultHandler {
Map<Integer,String> inMap = new HashMap<Integer,String>();
public Map<Integer, String> getIdNameMap() {
return inMap;
}
@Override
public void handleResult(ResultContext rc) {
@SuppressWarnings("unchecked")
Map<String,Object> m = (Map<String,Object>)rc.getResultObject();
inMap.put((Integer)getFromMap(m, "id"),
(String)getFromMap(m, "name"));
}
// see note at bottom of answer as to why I include this method
private Object getFromMap(Map<String, Object> map, String key) {
if (map.containsKey(key.toLowerCase())) {
return map.get(key.toLowerCase());
} else {
return map.get(key.toUpperCase());
}
}
}
La méthode handleResult est appelée une fois par ligne dans la table des catégories. Vous dites à MyBatis d'utiliser le ResultHandler puis d'extraire votre carte principale comme ceci:
CategoryResultHandler rh = new CategoryResultHandler();
session.select("getAllCategories", rh);
Map<Integer,String> m = rh.getIdNameMap();
L'un de ces deux devrait fonctionner pour vous.
Quelques notes finales:
Pourquoi ai-je inclus la méthode d'assistance getFromMap()
? Parce que vous ne pouvez pas toujours contrôler la casse du nom de colonne dans la table de hachage renvoyée par MyBatis. Plus de détails ici: mybatis- 3.1.1. Comment surcharger le resultmap retourné par mybatis
J'ai des exemples de travail de ces solutions dans Koan26 des mybatis-koans (que j'ai ajouté en fonction de votre question): https://github.com/midpeter444/mybatis-koans