I have not tried it on the select. Good idea. I will do that and post back any new information.
I don't know how I would be more explicit for the INSERT. Do I have to decompose the definition of the parameter class? Given that I know from the debugger that the typehandler is definitely called on the INSERT, what benefit would that bring? On 05/11/2007, Niels Beekman <[EMAIL PROTECTED]> wrote: > > Have you tried to define the typehandler explicitly on the resultmap or > insert statement? Do both select and insert blow up? > > > > Niels > ------------------------------ > > *From:* Raymond McDermott [mailto:[EMAIL PROTECTED] > *Sent:* maandag 5 november 2007 10:45 > *To:* [email protected] > *Subject:* Re: JAVA 1.5 enum > typehandler woes > > > > Thanks for the comments Niels. I read the FAQ entry completely before > posting and used it to drive the coded solution. > > In terms of the stacktrace, it is the complete stacktrace from Eclipse. I > think it gives enough to show that there is genuinely a problem with the > typehandler. > > I have debugged it all the way line by line, including adding the iBATIS > source code to the project. The data is good and it should return a valid > value - this is shown in the debugger - but somehow between the typehandler > returning a value from the ENUM and coming back into iBATIS, the value goes > null. > > That is why I wondered if there is something that I needed to do with the > enum itself? > > Thanks for the continued support. > > Ray > > On 05/11/2007, *Niels Beekman* <[EMAIL PROTECTED]> wrote: > > Hi, > > > > Are you sure this is the complete stacktrace? Did you try debugging? > > This error can be caused by numerous things, for example the property > frequency can be null in your bean, ensure that you are handling the > null-case in your typehandler, for a comprehensive explanation, see: > > > http://opensource.atlassian.com/confluence/oss/display/IBATIS/How+do+I+use+a+Custom+Type+Handler+with+complex+property+or+Type+Safe+Enumeration > > > > Hth, > > > > Niels > ------------------------------ > > *From:* Raymond McDermott [mailto:[EMAIL PROTECTED] > *Sent:* zondag 4 november 2007 21:57 > *To:* [email protected] > *Subject:* JAVA 1.5 enum > typehandler woes > > > > I am having some, ahem, fun trying to get enums persisting as varchars > using iBatis 2.3 for Java > > Can I just check something... is there are a 'proper' way for iBATIS to > persist enums or do we really have to write a typehandler? Is this is > something that the developer group will patch in 2.x or is there something > more fundamental in the architecture that makes it a 3.0 feature? > > Also, I wonder if i have to do something extra in the definition of an > ENUM to support access by the typehandler framework? > > Anyway, for the moment it seems that we are stuck with the, IMHO overly > complex, task of scripting support for our enum types. I am getting null > pointers despite debugging the code and seeing that the typehandler is being > properly registered and invoked. > > I have a simple enum class 'frequency': > > ---> ENUM START > > /** > * The frequency over which measurements are made > */ > > public enum Frequency { > DAILY, > WEEKLY, > MONTHLY, > YEARLY > } > > > ---> ENUM END > > I used the generic enum typehandler from the FAQ: > > ---> GENERIC TYPEHANDLER START > > import java.sql.SQLException; > > import com.ibatis.sqlmap.client.extensions.ParameterSetter; > import com.ibatis.sqlmap.client.extensions.ResultGetter; > import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback ; > > public abstract class EnumTypeHandler<E extends Enum> implements > TypeHandlerCallback > { > private Class<E> enumClass_; > > public EnumTypeHandler(Class<E> enumClass) > { > enumClass_ = enumClass; > } > > @SuppressWarnings("unchecked") > public void setParameter(ParameterSetter setter, Object parameter) > throws SQLException > { > setter.setString(((E) parameter).name()); > } > > public Object getResult(ResultGetter getter) throws SQLException > { > return valueOf(getter.getString()); > } > > @SuppressWarnings("unchecked") > public Object valueOf(String s) > { > return Enum.valueOf(enumClass_, s); > } > } > > ---> GENERIC TYPEHANDLER END > > Then I have the simple implementation as proposed in the FAQ: > > ---> SPECIFIC TYPEHANDLER START > > public class FrequencyTypeHandler extends EnumTypeHandler<Frequency> { > > public FrequencyTypeHandler() { > super(Frequency.class); > } > > } > > ---> SPECIFIC TYPEHANDLER END > > ---> IBATIS CONFIGURATION FILE START > > <?xml version="1.0" encoding="UTF-8" ?> > > <!DOCTYPE sqlMapConfig > PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" > "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> > > <sqlMapConfig> > > <typeHandler javaType=" com.opengrail.circles365.domain.Frequency" > jdbcType="VARCHAR" > callback=" > com.opengrail.circles365.config.ibatis.typehandlers.FrequencyTypeHandler"/> > > > <typeHandler javaType=" > com.opengrail.circles365.domain.MeasurementType" > jdbcType="VARCHAR" > callback=" > com.opengrail.circles365.config.ibatis.typehandlers.MeasurementTypeTypeHandler"/> > > > <!-- List the SQL Map XML files. They can be loaded from the > classpath, as they are here (com.domain.data...) --> > > <sqlMap resource="com/opengrail/circles365/config/iBatis- User.xml"/> > <sqlMap resource="com/opengrail/circles365/config/iBatis- > MeasurementItem.xml"/> > > </sqlMapConfig> > > ---> IBATIS CONFIGURATION FILE END > > ---> IBATIS SQLMAP FILE START > > <?xml version="1.0" encoding="UTF-8" ?> > > <!DOCTYPE sqlMap > PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" > " http://ibatis.apache.org/dtd/sql-map-2.dtd"> > > <sqlMap namespace="MeasurementItem"> > > <resultMap id="result" class=" > com.opengrail.circles365.domain.impl.MeasurementItemImpl "> > <result property="frequency" column="FREQUENCY"/> > <result property="measurementType" column="MEASUREMENTTYPE"/> > <result property="name" column="ITEMNAME"/> > <result property="derived" column="ISDERIVED"/> > </resultMap> > > <select id="findMeasurementItemsByUserId" resultMap="result"> > select FREQUENCY, MEASURETYPE, ITEMNAME, ISDERIVED > from C365MEASUREMENTITEM MI, C365USER U > where U.USERID = #value# > and MI.USERID = U.ID > </select> > > <insert id="createMeasurementItem" parameterClass=" > com.opengrail.circles365.domain.MeasurementItem"> > insert > into C365MEASUREMENTITEM (frequency, measuretype, itemname, > isderived, userid) > select #frequency#, #measurementType#, #name#, #derived#, > u.id > from c365user u > where u.userid = #userId# > </insert> > > </sqlMap> > > ---> IBATIS SQLMAP FILE END > > Unit test trace ON INSERT: > > org.springframework.jdbc.UncategorizedSQLException: SqlMapClient > operation; uncategorized SQLException for SQL []; SQL state [null]; error > code [0]; > --- The error occurred in com/opengrail/circles365/config/iBatis- > MeasurementItem.xml. > --- The error occurred while applying a parameter map. > --- Check the createMeasurementItem-InlineParameterMap. > --- Check the parameter mapping for the 'frequency' property. > --- Cause: java.lang.NullPointerException; nested exception is > com.ibatis.common.jdbc.exception.NestedSQLException: > --- The error occurred in com/opengrail/circles365/config/iBatis- > MeasurementItem.xml. > --- The error occurred while applying a parameter map. > *--- Check the createMeasurementItem-InlineParameterMap. > --- Check the parameter mapping for the 'frequency' property. > *--- Cause: java.lang.NullPointerException > Caused by: com.ibatis.common.jdbc.exception.NestedSQLException: > --- The error occurred in com/opengrail/circles365/config/iBatis- > MeasurementItem.xml . > --- The error occurred while applying a parameter map. > --- Check the createMeasurementItem-InlineParameterMap. > --- Check the parameter mapping for the 'frequency' property. > --- Cause: java.lang.NullPointerException > at > com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate( > GeneralStatement.java:94) > at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update( > SqlMapExecutorDelegate.java:505) > at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.update( > SqlMapSessionImpl.java:90) > at > org.springframework.orm.ibatis.SqlMapClientTemplate$10.doInSqlMapClient( > SqlMapClientTemplate.java:383) > at org.springframework.orm.ibatis.SqlMapClientTemplate.execute ( > SqlMapClientTemplate.java:193) > at org.springframework.orm.ibatis.SqlMapClientTemplate.update( > SqlMapClientTemplate.java:381) > at > com.opengrail.circles365.data.impl.MeasurementItemDaoImpl.createMeasurementItem( > MeasurementItemDaoImpl.java:13) > at > com.opengrail.circles365.service.impl.MeasurementItemManagementImpl.createMeasurementItem > (MeasurementItemManagementImpl.java:25) > at > com.opengrail.circles365.tests.ServiceImplementationTests.testGoodMeasurementItem( > ServiceImplementationTests.java:56) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at sun.reflect.NativeMethodAccessorImpl.invoke( > NativeMethodAccessorImpl.java:39) > at sun.reflect.DelegatingMethodAccessorImpl.invoke ( > DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:585) > at junit.framework.TestCase.runTest(TestCase.java:154) > at junit.framework.TestCase.runBare(TestCase.java:127) > at org.springframework.test.ConditionalTestCase.runBare( > ConditionalTestCase.java:69) > at junit.framework.TestResult$1.protect(TestResult.java:106) > at junit.framework.TestResult.runProtected(TestResult.java :124) > at junit.framework.TestResult.run(TestResult.java:109) > at junit.framework.TestCase.run(TestCase.java:118) > at junit.framework.TestSuite.runTest(TestSuite.java:208) > at junit.framework.TestSuite.run (TestSuite.java:203) > at > org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run( > JUnit3TestReference.java:130) > at org.eclipse.jdt.internal.junit.runner.TestExecution.run( > TestExecution.java:38) > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests( > RemoteTestRunner.java:460) > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests( > RemoteTestRunner.java:673) > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run ( > RemoteTestRunner.java:386) > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main( > RemoteTestRunner.java:196) > Caused by: java.lang.NullPointerException > at > com.ibatis.sqlmap.engine.mapping.parameter.BasicParameterMap.setParameter( > BasicParameterMap.java:165) > at > com.ibatis.sqlmap.engine.mapping.parameter.BasicParameterMap.setParameters > (BasicParameterMap.java:125) > at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate( > SqlExecutor.java :79) > at > com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteUpdate > (GeneralStatement.java:200) > at > com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate( > GeneralStatement.java :78) > ... 27 more > > Do any of you folks have any ideas? > > Thanks in advance for your support. > > Ray > > > > > -- > Ray McDermott > GSM 047/32.53.854 > -- Ray McDermott GSM 047/32.53.854
