Title: Problem with HashMap and List
Hi,
I've just encountered a big problem with my iBatis-Application. First I implemented a DOM and used it in the class=-Properties of my resultMaps. Now we decided, to change the architecture to a HashMap-Structure of the following: HashMap as some Lists as values: the Lists have HashMaps again. Here is an example of my xml-File to illustrate, what I want to do:
resultMap id=a class=java.util.HashMap
result property=aa select=loadAA/
result property=id column=id/
/resultMap
select id=loadA resultMap=a
Select id from tableA where id = 1
/select
resultMap id=aa class=java.util.HashMap
result property=id column=id/
/resultMap
select id=loadAA resultMap=aa
Select id from tableA
/select
The first select returns one result -- a HashMap, the second select returns numerous results -- n HashMaps that should be mapped as a List of HashMaps.
When we implement it as a DOM and exchange the classes in the resultMaps with the ones below, the same code works fine:
class A {
private Collection aa;
private int id;
//getters and setters
}
class AA {
private int id;
}
When we try to run the application we get:
Exception in thread main org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [null]; error code [0];
--- The error occurred in test.xml.
--- The error occurred while applying a result map.
--- Check the a.
--- Check the result mapping for the 'aa' property.
--- Cause: java.sql.SQLException: Error: executeQueryForObject returned too many results.; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
After reviewing the sources we've come up with an explanation:
The Method BasicResultMap.getResults(RequestScope request, ResultSet rs) the targetType for further calls is set:
if (resultClass == null) {
throw new SqlMapException(The result class was null when trying to get results for ResultMap named + getId() + .);
} else if (Map.class.isAssignableFrom(resultClass)) {
columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, Object.class);
} else if (DomTypeMarker.class.isAssignableFrom(resultClass)) {
Class javaType = mapping.getJavaType();
if (javaType == null) {
javaType = DomTypeMarker.class;
}
columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, javaType);
} else {
Probe p = ProbeFactory.getProbe(resultClass);
Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName());
columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, type);
}
So, how can we get around this? If the else-Statements would be something like:
if (resultClass == null) {
throw new SqlMapException(The result class was null when trying to get results for ResultMap named + getId() + .);
} else if (DomTypeMarker.class.isAssignableFrom(resultClass)) {
Class javaType = mapping.getJavaType();
if (javaType == null) {
javaType = DomTypeMarker.class;
}
columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, javaType);
} else if (Map.class.isAssignableFrom(resultClass)) {
columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, Object.class);
} else {
Probe p = ProbeFactory.getProbe(resultClass);
Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName());
columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, type);
}
Our problem would be solvalbe implementing a DummyDO-Class:
class DummyDO extends HashMap implements DomTypeMarker
BUT, due to the order of the else-Statements this doesn't work and again, targetType is set to java.lang.Object and later, the getQueryForObject-Method is called.
How can we get around this?
Stefan Friedrich