tag mvc multiple mkyong library form example attribute java spring-mvc mybatis ibatis

java - multiple - Regrese HashMap en mybatis y úselo como ModelAttribute en Spring MVC



spring mvc tag library (1)

Quiero mostrar una lista de categorías en mi página Jsp utilizando spring mvc @modelAttribute.

En mi archivo mapper.xml es

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

En mi clase Mapper.java tengo un método

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

Quiero tener un método como este:

Map<Integer, String>`selectAllCategories();

en lugar de List<Map<>> , ¿es eso posible?


Desea obtener un Map<Integer,String> donde el Entero es el id y la Cadena es el name . Si hubiera 200 categorías en su tabla, querría 200 entradas en su mapa, en lugar de una lista de 200 mapas.

MyBatis no puede hacer eso de inmediato, pero puede usar sus instalaciones para hacerlo. Veo dos opciones.

Opción 1:

El primero no es exactamente lo que pediste, pero vale la pena mostrarlo. Le da un Map<Integer,Category> donde Categoría es un objeto de dominio para la tabla de categorías que tiene identificación, nombre (y posiblemente otros campos de la tabla de categorías). Después de haber creado el objeto de dominio Categoría, esto es bastante fácil de hacer en MyBatis usando la anotación @MapKey :

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

En tu código, entonces harías:

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

Eso puede funcionar o no para su caso de uso, dependiendo de si puede extraer el nombre como una propiedad del objeto Categoría.


Opcion 2:

Para obtener el Map<Integer,String> que solicitó, la forma más fácil que conozco es crear una clase que implemente la interfaz MyBatis ResultHandler .

Su ResultHandler utilizará el hashmap predeterminado de column-name => column-value que MyBatis crea y crea un único mapa maestro. Aquí está el código:

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

El método handleResult se llama una vez por fila en la tabla de categorías. Le dices a MyBatis que use ResultHandler y luego extrae tu mapa maestro así:

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

Uno de esos dos debería funcionar para usted.

Algunas notas finales:

  1. ¿Por qué getFromMap() método de ayuda getFromMap() ? Porque no siempre se puede controlar el caso del nombre de la columna en el hashmap que devuelve MyBatis. Más detalles aquí: mybatis- 3.1.1. cómo anular el mapa de resultados devuelto por mybatis

  2. Tengo ejemplos prácticos de estas soluciones en Koan26 de mybatis-koans (que agregué en función de su pregunta): https://github.com/midpeter444/mybatis-koans