Верните HashMap в mybatis и используйте его как ModelAttribute в spring MVC

Я хочу отобразить список категорий на моей странице Jsp с помощью spring mvc @modelAttribute.

в моем картографа.xml-файл

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

в моем картографа.класс java у меня есть метод

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

Я хочу иметь метод такой:

Map<Integer, String>`selectAllCategories();

вместо List<Map<>>, это возможно?

1 ответов


вы хотите получить Map<Integer,String> где целым числом является id и в строке name. Если бы в вашей таблице было 200 категорий, вам понадобилось бы 200 записей на карте, а не список из 200 карт.

MyBatis не может сделать это из коробки, но вы можете использовать его возможности для этого. Я вижу два варианта.

Вариант 1:

первый не совсем то, что вы просили, но стоит показать. Это дает вам Map<Integer,Category> где Category-объект домена для таблицы categories, который имеет id, name (и, возможно, другие поля из таблицы categories). После того как вы создали объект домена категории, это довольно легко сделать в MyBatis с помощью @MapKey аннотация:

@Select("SELECT id, name FROM categories")
@MapKey("id")
Map<Integer,Category> getAllCategories();

в вашем коде вы бы сделали:

MyMapper mapper = session.getMapper(MyMapper.class);
Map<Integer,Category> m = mapper.getAllCategories();

что может или не может работать для вашего варианта использования, в зависимости от того, можно ли извлечь имя как свойство категории объект.


Вариант 2:

для получения Map<Integer,String> вы просили, самый простой способ, который я знаю, это создать класс, который реализует MyBatis ResultHandler интерфейс.

ваш ResultHandler будет использовать хэш-карту по умолчанию column-name => column-value, которую MyBatis создает и создает одну главную карту. Вот код:

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());
    }
  }
}

метод handleResult вызывается один раз в строке в категории таблица. Вы говорите MyBatis использовать ResultHandler, а затем извлечь мастер-карту, как это:

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

один из этих двух должен работать для вас.

несколько заключительных нот:

  1. почему я включил getFromMap() вспомогательный метод? Потому что вы не всегда можете контролировать регистр имени столбца в hashmap, который возвращает MyBatis. Подробнее здесь:mybatis - 3.1.1. как переопределить resultmap, возвращенный из mybatis

  2. у меня есть рабочие примеры этих решений в Koan26 из mybatis-koans (которые я добавил на основе вашего вопроса):https://github.com/midpeter444/mybatis-koans