I followed your advice on the typehandler properties on the select statement
and it started to work. Great!
I also have to rescind one of my earlier statements. I did some more
debugging on the INSERT statement and although the property values are all
being set nicely, there was no typehandler :(
So I looked again at the manual and at the typeHandler definitions. The
reason that it does not associate the typehandler with the correct types is
that I have incorrectly specced the type handler thus:
<typeHandler javaType="domain.Frequency"
jdbcType="VARCHAR"
callback="typehandlers.FrequencyTypeHandler"/>
Once I removed the jdbcType it all started to work nicely :)
<typeHandler javaType="domain.Frequency"
callback="typehandlers.FrequencyTypeHandler"/>
So all is well that ends well.
Thanks for the pointers and the support.
Best regards
Ray
On 05/11/2007, Raymond McDermott <[EMAIL PROTECTED]> wrote:
>
> 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.0feature?
> >
> > 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
>
--
Ray McDermott
GSM 047/32.53.854