지금 회사에서 ibatis 버전 2.3.4.726 을 사용 하고 있습니다. 이용할때 뜨문뜨문 에러가 발생했습니다. 에러 메시지는 아래와 같이 나왔습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13
CLASS_NAME : MappedStatement.java / LINE : 211 / MESSAGE : com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in com/mobon/dao/sql/mobon.xml. --- The error occurred while applying a result map. --- Check the mobon.selAdInfo-AutoResultMap. --- The error happened while setting a property on the result object. --- Cause: net.sf.cglib.beans.BulkBeanException CLASS_NAME : MappedStatement.java / LINE : 144 / MESSAGE : com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in com/mobon/dao/sql/mobon.xml. --- The error occurred while applying a result map. --- Check the mobon.selAdInfo-AutoResultMap. --- The error happened while setting a property on the result object. --- Cause: net.sf.cglib.beans.BulkBeanException
에러 메시지를 보고 궁금증이 들어서 ibatis code를 보았습니다. 에러가 났던 클래스는 MappedStatement.java(com.ibatis.sqlmap.engine.mapping.statement 패키지에 있습니다.) 에러가 난 메소드를 보면 아래와 같은 코드 입니다.
protectedvoidexecuteQueryWithCallback(StatementScope statementScope, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults) throws SQLException { // conn.setReadOnly(isReadOnly()); // added by yseun
ErrorContexterrorContext= statementScope.getErrorContext(); errorContext.setActivity("preparing the mapped statement for execution"); errorContext.setObjectId(this.getId()); errorContext.setResource(this.getResource());
public Object[] getResults(StatementScope statementScope, ResultSet rs) throws SQLException { ErrorContexterrorContext= statementScope.getErrorContext(); errorContext.setActivity("applying a result map"); errorContext.setObjectId(this.getId()); errorContext.setResource(this.getResource()); errorContext.setMoreInfo("Check the result map.");
booleanfoundData=false; Object[] columnValues = newObject[getResultMappings().length]; for (inti=0; i < getResultMappings().length; i++) { ResultMappingmapping= (ResultMapping) getResultMappings()[i]; errorContext.setMoreInfo(mapping.getErrorString()); if (mapping.getStatementName() != null) { if (resultClass == null) { thrownewSqlMapException("The result class was null when trying to get results for ResultMap named " + getId() + "."); } elseif (Map.class.isAssignableFrom(resultClass)) { ClassjavaType= mapping.getJavaType(); if (javaType == null) { javaType = Object.class; } columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType); } elseif (DomTypeMarker.class.isAssignableFrom(resultClass)) { ClassjavaType= mapping.getJavaType(); if (javaType == null) { javaType = DomTypeMarker.class; } columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType); } else { Probep= ProbeFactory.getProbe(resultClass); Classtype= p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName()); columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, type); } foundData = foundData || columnValues[i] != null; } elseif (mapping.getNestedResultMapName() == null) { columnValues[i] = getPrimitiveResultMappingValue(rs, mapping); if (columnValues[i] == null) { columnValues[i] = doNullMapping(columnValues[i], mapping); } else { foundData = true; } } }
다시 SqlExecutor에 handleResults 메소드를 보면 getResults 후에 callback.handleResultObject 호출 하는데 RowHandlerCallback.java(com.ibatis.sqlmap.engine.mapping.statement 패키지) class를 보면
if (object != ResultMap.NO_VALUE) { // XML Only special processing. (converts elements to string for easy insertion). intstackDepth= statementScope.getSession().getRequestStackDepth(); if (stackDepth == 1) { ClasstargetType= statementScope.getResultMap().getResultClass(); if (XmlTypeMarker.class.isAssignableFrom(targetType) && object instanceof Document) { object = documentToString((Document) object); } }
rowHandler.handleRow(object); } }
setResultObjectValues 메소드를 호출하는데 다시 찾아 보면 AutoResultMap.java(com.ibatis.sqlmap.engine.mapping.result 패키지) class의 setResultObjectValues 호출
1 2 3 4 5 6 7 8 9 10 11 12
public Object setResultObjectValues(StatementScope statementScope, Object resultObject, Object[] values) { // synchronization is only needed when remapping is enabled if (allowRemapping) { synchronized (this) { returnsuper.setResultObjectValues(statementScope, resultObject, values); } } returnsuper.setResultObjectValues(statementScope, resultObject, values); }
여기까지 오면 거의 다옴 그럼 여기서 보면 dataExchange.setData 를 호출함 DataExchange 를 상속받은 것이 여러가지가 있는데 우리가 볼것은 JavaBeanDataExchange.java(com.ibatis.sqlmap.engine.exchange 패키지) class에 setData 메소드
```java
public Object setData(StatementScope statementScope, ResultMap resultMap, Object resultObject, Object[] values) { if (resultPlan != null) { Objectobject= resultObject;
if (object == null) { errorContext.setMoreInfo("The error occured while instantiating the result object"); try { object = ResultObjectFactoryUtil.createObjectThroughFactory(resultMap.getResultClass()); } catch (Exception e) { thrownewRuntimeException("JavaBeansDataExchange could not instantiate result class. Cause: " + e, e); } } errorContext.setMoreInfo("The error happened while setting a property on the result object."); resultPlan.setProperties(object, values); return object; } else { returnnull; } }
최종 오류는 resultPlan.setProperties 하는 시점에 나온것이다 그럼 찾아 들어가면 AccessPlan.java 도 여러가지 클래스가 구현하고 있는데 EnhancedPropertyAccessPlan.java(com.ibatis.sqlmap.engine.accessplan 패키지) 클래스를 확인 하면