Change proposal for BasicResultMap.getResults(RequestScope request, ResultSet rs)

2006-02-10 Thread Ext_Friedrich, Stefan
Title: Change proposal for BasicResultMap.getResults(RequestScope request, ResultSet rs) 






Hi,


We tried to implement the HashMaps as results for our queries. The problem is, that whenever a HashMap is set as the resultClass, a queryForObject is called and so, every select can only return ONE result. In our application we expect a list of HashMaps at certain locations. The solution for our problem would be very simple and - in our opinion - would work with only three new lines of code:


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




The bold part would have to be changed (exactly like the next else-Statement):



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)) { 

 Class javaType = mapping.getJavaType();
 if (javaType == null) {
  javaType = Object.class;
 }
 columnValues[i] = getNestedSelectMappingValue(request, rs, mapping, javaType);
} 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);
}


As you can see, the changes would have no effect, if no javaType was set. But for our concerns, we would set the javaType to java.util.ArrayList and everything would be just fine!


Stefan





Problem with HashMap and List

2006-02-09 Thread Ext_Friedrich, Stefan
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