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:
¿Por qué
getFromMap()
método de ayudagetFromMap()
? 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 mybatisTengo 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