Retourner HashMap dans mybatis et l'utiliser comme ModelAttribute au printemps MVC

je veux afficher la liste des catégories dans ma page Jsp en utilisant MVC @modelAttribute de printemps.

dans mon compte.le fichier xml est

<select id="selectAllCategories" resultMap="BaseResultMap">
  select id, name from categories  
</select>

dans mon compte.la classe java j'ai de la méthode

List<Map<String, String>> selectAllCategories();

je veux une méthode comme celle-ci:

Map<Integer, String>`selectAllCategories();

au lieu de List<Map<>> , est-ce possible?

20
demandé sur Dariusz 2012-08-11 11:49:48

1 réponses

vous voulez obtenir un Map<Integer,String> où L'entier est le id et la chaîne de caractères est le name . Si il y avait 200 catégories dans votre tableau, vous souhaitez 200 entrées de votre carte, plutôt qu'une liste de 200 cartes.

MyBatis peut pas tout faire hors de la boîte, mais vous pouvez utiliser ses installations pour le faire. Je vois deux options.

Option 1:

le premier n'est pas tout à fait ce vous avez demandé mais cela vaut la peine de le montrer. Il vous donne un Map<Integer,Category> où Category est un objet de domaine pour la table categories qui a id, name (et éventuellement d'autres champs de la table categories). Après avoir créé L'objet de domaine de catégorie, C'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();

qui peut ou ne peut pas fonctionner pour votre cas d'utilisation selon si vous pouvez extraire le nom comme une propriété de l'objet de catégorie.



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 le hashmap par défaut de column-name = > column-valeur que MyBatis crée et créer une carte maître unique. 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 de catégorie. Vous dites à MyBatis d'utiliser le Gestionnaire de résultats et puis extraire votre carte maîtresse comme ceci:

CategoryResultHandler rh = new CategoryResultHandler();
session.select("getAllCategories", rh);
Map<Integer,String> m = rh.getIdNameMap();

l'un de ces deux devrait travailler pour vous.

quelques notes finales:

  1. Pourquoi ai-je inclus la méthode getFromMap() helper? Parce que vous ne pouvez pas toujours contrôler le cas du nom de colonne dans le hashmap que MyBatis renvoie. Plus de détails ici: mybatis-3.1.1. comment modifier le résultat de l'image retournée de mybatis

  2. J'ai des exemples de travail de ces solutions dans Koan26 du mybatis-koans (que j'ai ajouté basé sur votre question): https://github.com/midpeter444/mybatis-koans

37
répondu quux00 2017-05-23 11:46:34