You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by jg...@apache.org on 2006/11/27 17:53:04 UTC
svn commit: r479687 - in /ibatis/trunk/java/mapper/mapper2: build/
src/com/ibatis/common/beans/ src/com/ibatis/sqlmap/engine/exchange/
src/com/ibatis/sqlmap/engine/execution/
src/com/ibatis/sqlmap/engine/mapping/result/
Author: jgbutler
Date: Mon Nov 27 08:53:03 2006
New Revision: 479687
URL: http://svn.apache.org/viewvc?view=rev&rev=479687
Log:
Fixes for IBATIS-366: Use ResultObjectFactory for nested classes
Modified:
ibatis/trunk/java/mapper/mapper2/build/version.properties
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ComplexBeanProbe.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/ComplexDataExchange.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/JavaBeanDataExchange.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/BasicResultMap.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactory.java
ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactoryUtil.java
Modified: ibatis/trunk/java/mapper/mapper2/build/version.properties
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/build/version.properties?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/build/version.properties (original)
+++ ibatis/trunk/java/mapper/mapper2/build/version.properties Mon Nov 27 08:53:03 2006
@@ -1,5 +1,5 @@
#Build version info
-#Mon Nov 20 22:45:11 MST 2006
+#Mon Nov 27 10:29:35 CST 2006
version=2.3.0
-buildDate=2006/11/20 22\:45
-buildNum=669
+buildDate=2006/11/27 10\:29
+buildNum=671
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ComplexBeanProbe.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ComplexBeanProbe.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ComplexBeanProbe.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/common/beans/ComplexBeanProbe.java Mon Nov 27 08:53:03 2006
@@ -19,6 +19,8 @@
import java.util.Map;
import java.util.StringTokenizer;
+import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil;
+
/**
* StaticBeanProbe provides methods that allow simple, reflective access to
* JavaBeans style properties. Methods are provided for all simple types as
@@ -219,7 +221,7 @@
return; // don't instantiate child path if value is null
} else {
try {
- child = type.newInstance();
+ child = ResultObjectFactoryUtil.createObjectThroughFactory(type);
setObject(parent, property, child);
} catch (Exception e) {
throw new ProbeException("Cannot set value of property '" + name + "' because '" + property + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/ComplexDataExchange.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/ComplexDataExchange.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/ComplexDataExchange.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/ComplexDataExchange.java Mon Nov 27 08:53:03 2006
@@ -18,7 +18,6 @@
import com.ibatis.common.beans.Probe;
import com.ibatis.common.beans.ProbeFactory;
-import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;
import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
@@ -78,9 +77,7 @@
Object object = resultObject;
if (object == null) {
try {
- ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
- object = ResultObjectFactoryUtil.createObjectThroughFactory(client.getResultObjectFactory(),
- request.getStatement().getId(), resultMap.getResultClass());
+ object = ResultObjectFactoryUtil.createObjectThroughFactory(resultMap.getResultClass());
} catch (Exception e) {
throw new RuntimeException("JavaBeansDataExchange could not instantiate result class. Cause: " + e, e);
}
@@ -101,9 +98,7 @@
Object object = parameterObject;
if (object == null) {
try {
- ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
- object = ResultObjectFactoryUtil.createObjectThroughFactory(client.getResultObjectFactory(),
- request.getStatement().getId(), parameterMap.getParameterClass());
+ object = ResultObjectFactoryUtil.createObjectThroughFactory(parameterMap.getParameterClass());
} catch (Exception e) {
throw new RuntimeException("JavaBeansDataExchange could not instantiate result class. Cause: " + e, e);
}
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/JavaBeanDataExchange.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/JavaBeanDataExchange.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/JavaBeanDataExchange.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/exchange/JavaBeanDataExchange.java Mon Nov 27 08:53:03 2006
@@ -18,7 +18,6 @@
import com.ibatis.sqlmap.engine.accessplan.AccessPlan;
import com.ibatis.sqlmap.engine.accessplan.AccessPlanFactory;
-import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;
import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
@@ -104,9 +103,7 @@
if (object == null) {
errorContext.setMoreInfo("The error occured while instantiating the result object");
try {
- ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
- object = ResultObjectFactoryUtil.createObjectThroughFactory(client.getResultObjectFactory(),
- request.getStatement().getId(), resultMap.getResultClass());
+ object = ResultObjectFactoryUtil.createObjectThroughFactory(resultMap.getResultClass());
} catch (Exception e) {
throw new RuntimeException("JavaBeansDataExchange could not instantiate result class. Cause: " + e, e);
}
@@ -125,9 +122,7 @@
Object object = parameterObject;
if (object == null) {
try {
- ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
- object = ResultObjectFactoryUtil.createObjectThroughFactory(client.getResultObjectFactory(),
- request.getStatement().getId(), parameterMap.getParameterClass());
+ object = ResultObjectFactoryUtil.createObjectThroughFactory(parameterMap.getParameterClass());
} catch (Exception e) {
throw new RuntimeException("JavaBeansDataExchange could not instantiate parameter class. Cause: " + e, e);
}
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/execution/SqlExecutor.java Mon Nov 27 08:53:03 2006
@@ -19,6 +19,7 @@
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;
import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
+import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil;
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;
import com.ibatis.sqlmap.engine.scope.ErrorContext;
@@ -68,6 +69,7 @@
errorContext.setActivity("executing update");
errorContext.setObjectId(sql);
PreparedStatement ps = null;
+ setupResultObjectFactory(request);
int rows = 0;
try {
errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
@@ -164,6 +166,7 @@
errorContext.setObjectId(sql);
PreparedStatement ps = null;
ResultSet rs = null;
+ setupResultObjectFactory(request);
try {
errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
Integer rsType = request.getStatement().getResultSetType();
@@ -211,6 +214,7 @@
errorContext.setActivity("executing update procedure");
errorContext.setObjectId(sql);
CallableStatement cs = null;
+ setupResultObjectFactory(request);
int rows = 0;
try {
errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
@@ -251,6 +255,7 @@
errorContext.setObjectId(sql);
CallableStatement cs = null;
ResultSet rs = null;
+ setupResultObjectFactory(request);
try {
errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
Integer rsType = request.getStatement().getResultSetType();
@@ -666,4 +671,9 @@
}
}
+ private void setupResultObjectFactory(RequestScope request) {
+ ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
+ ResultObjectFactoryUtil.setResultObjectFactory(client.getResultObjectFactory());
+ ResultObjectFactoryUtil.setStatementId(request.getStatement().getId());
+ }
}
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/BasicResultMap.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/BasicResultMap.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/BasicResultMap.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/BasicResultMap.java Mon Nov 27 08:53:03 2006
@@ -436,9 +436,7 @@
// then we will just set the property to the object created
// in processing the nested result map
if (Collection.class.isAssignableFrom(type)) {
- ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
- obj = ResultObjectFactoryUtil.createObjectThroughFactory(client.getResultObjectFactory(),
- request.getStatement().getId(), type);
+ obj = ResultObjectFactoryUtil.createObjectThroughFactory(type);
PROBE.setObject(resultObject, propertyName, obj);
}
} catch (Exception e) {
@@ -574,9 +572,7 @@
if (parameterType == null) {
parameterObject = new HashMap();
} else {
- ExtendedSqlMapClient client = (ExtendedSqlMapClient) request.getSession().getSqlMapClient();
- parameterObject = ResultObjectFactoryUtil.createObjectThroughFactory(client.getResultObjectFactory(),
- request.getStatement().getId(), parameterType);
+ parameterObject = ResultObjectFactoryUtil.createObjectThroughFactory(parameterType);
}
String complexName = mapping.getColumnName();
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactory.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactory.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactory.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactory.java Mon Nov 27 08:53:03 2006
@@ -21,6 +21,9 @@
* your implementation class as the type for the "resultObjectFactory"
* element in the SqlMapConfig. Any implementation of this interface
* must have a public no argument constructor.
+ *
+ * Note that iBATIS makes use of this interface through the
+ * ResultObjectFactoryUtil class.
*
* @author Jeff Butler
*
@@ -42,7 +45,7 @@
* <li>When processing result maps with nested result maps. iBATIS will
* ask the factory to create an instance of the nested object. If the nested
* object is some implementation of <code>java.util.Collection</code>
- * then iBATIS will suppliy default implementations of the common interfaces
+ * then iBATIS will supply default implementations of the common interfaces
* if the factory chooses not to create the object. If the
* embedded object is a <code>java.util.List</code> or
* <code>java.util.Collection</code> the default behavior is to
Modified: ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactoryUtil.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactoryUtil.java?view=diff&rev=479687&r1=479686&r2=479687
==============================================================================
--- ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactoryUtil.java (original)
+++ ibatis/trunk/java/mapper/mapper2/src/com/ibatis/sqlmap/engine/mapping/result/ResultObjectFactoryUtil.java Mon Nov 27 08:53:03 2006
@@ -24,11 +24,32 @@
import com.ibatis.common.resources.Resources;
/**
- * @author Jeff Butler
+ * This class is used to create instances of result objects. It will
+ * use the configured ResultObjectFactory if there is one, otherwise
+ * it will use iBATIS' normal methods.
+ *
+ * Note that this class is somewhat tightly coupled with
+ * SqlExecuter - SqlExecute must call the setStatementId() and
+ * setResultObjectFactory() methods before executing a statement.
+ * This is a result of using a ThreadLocal to hold the current
+ * configuration for the statement under execution. Using a
+ * ThreadLocal is a solution for IBATIS-366. Without a ThreadLocal,
+ * the current factory and statement id would have to be added to
+ * many method signatures - often in inappropriate places.
*
+ * @author Jeff Butler
*/
public class ResultObjectFactoryUtil {
-
+
+ /**
+ * Use a ThreadLocal to hold the current statementId and
+ * factory. This is much easier than passing these
+ * items all over the place, and it has no measurable impact on
+ * performance (I did a test with 100000 result rows and found
+ * no impact - Jeff Butler).
+ */
+ private static ThreadLocal factorySettings = new ThreadLocal();
+
/**
* Utility class - no instances
*/
@@ -64,15 +85,16 @@
* Exception, iBATIS will throw a runtime exception in response and
* will end.
*/
- public static Object createObjectThroughFactory(ResultObjectFactory factory,
- String statementId, Class clazz) throws InstantiationException,
+ public static Object createObjectThroughFactory(Class clazz) throws InstantiationException,
IllegalAccessException {
+ FactorySettings fs = getFactorySettings();
+
Object obj;
- if (factory == null) {
+ if (fs.getResultObjectFactory() == null) {
obj = createObjectInternally(clazz);
} else {
- obj = factory.createInstance(statementId, clazz);
+ obj = fs.getResultObjectFactory().createInstance(fs.getStatementId(), clazz);
if (obj == null) {
obj = createObjectInternally(clazz);
}
@@ -104,5 +126,44 @@
Object obj = Resources.instantiate(classToCreate);
return obj;
+ }
+
+ public static void setResultObjectFactory(ResultObjectFactory resultObjectFactory) {
+ getFactorySettings().setResultObjectFactory(resultObjectFactory);
+ }
+
+ public static void setStatementId(String statementId) {
+ getFactorySettings().setStatementId(statementId);
+ }
+
+ private static FactorySettings getFactorySettings() {
+ FactorySettings fs = (FactorySettings) factorySettings.get();
+ if (fs == null) {
+ fs = new FactorySettings();
+ factorySettings.set(fs);
+ }
+
+ return fs;
+ }
+
+ private static class FactorySettings {
+ private ResultObjectFactory resultObjectFactory;
+ private String statementId;
+
+ public ResultObjectFactory getResultObjectFactory() {
+ return resultObjectFactory;
+ }
+
+ public void setResultObjectFactory(ResultObjectFactory resultObjectFactory) {
+ this.resultObjectFactory = resultObjectFactory;
+ }
+
+ public String getStatementId() {
+ return statementId;
+ }
+
+ public void setStatementId(String statementId) {
+ this.statementId = statementId;
+ }
}
}