ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Raymond McDermott" <...@mcdermott.be>
Subject Re: JAVA 1.5 enum > typehandler woes
Date Mon, 05 Nov 2007 16:02:38 GMT
Neils - I like your optimism and appreciate your faith in me ;-)

On 05/11/2007, Niels Beekman <n.beekman@wis.nl> wrote:
>
>  It seems that the ValueEnum interface is only needed when you want to
> persist the enum using customized names, instead of just the enum constant
> name itself. It still doesn't explain why you get a NPE when you have
> verified that iBATIS calls your typehandler. Can you try debugging some
> more, you should be able to find it…
>
>
>
> Niels
>  ------------------------------
>
> *From:* Raymond McDermott [mailto:ray@mcdermott.be]
> *Sent:* maandag 5 november 2007 16:25
> *To:* user-java@ibatis.apache.org; lmeadors@apache.org
> *Subject:* Re: JAVA 1.5 enum > typehandler woes
>
>
>
> I saw that option but, to be honest rather than critical, I made it the
> option of 'last resort'.
>
> If I understand it correctly, the design directly adds features to enums
> to allow them to work with iBATIS.
>
> For me it is a little inelegant and unnatural to have all my enums
> implement an interface for the sake of iBATIS.
>
> However at this point perhaps elegance is no longer so important ;-)
>
> Thanks for the post.
>
> Ray
>
>  On 05/11/2007, *Larry Meadors* < lmeadors@apache.org> wrote:
>
> Hey Ray,
>
> Did you see the other way to do this on the Wiki?
>
>
> http://opensource.atlassian.com/confluence/oss/display/IBATIS/How+do+I+use+Enums+with+annotations
>
> That is http://tinyurl.com/2mgqd3 if that gets buggered up by gmail.
>
> I do it a bit different and it's very little code - essentially, you
> tell a base type handler the enum class and the jdbc type, and the
> rest is done for you:
>
> @EnumTypeHandler(
>   enumClass = EmploymentTermReason.class,
>   jdbcType = Types.VARCHAR)
> public class EmploymentTermReasonTypeHandler extends EnumTypeHandlerImpl {
> }
>
> After that, you register some type aliases and the handler in your
> sqlmap config:
>
> <typeAlias
>   alias="EmploymentTermReason"
>   type="com.blah.EmploymentTermReason" />
> <typeAlias
>   alias="EmploymentTermReasonTypeHandler"
>   type=" com.blah.EmploymentTermReasonTypeHandler" />
> <typeHandler
>   javaType="EmploymentTermReason"
>   callback="EmploymentTermReasonTypeHandler" />
>
> BTW, the type aliases are optional, but save some typing and make
> refactoring easier.
>
> Larry
>
>
> On 11/5/07, Raymond McDermott <ray@mcdermott.be> 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 <n.beekman@wis.nl> 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:ray@mcdermott.be]
> > > Sent: maandag 5 november 2007 10:45
> > > To: user-java@ibatis.apache.org
> > > 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 < n.beekman@wis.nl > 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: ray@mcdermott.be ]
> > > Sent: zondag 4 november 2007 21:57
> > > To: user-java@ibatis.apache.org
> > > 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
>
>
>
>
> --
> Ray McDermott
> GSM 047/32.53.854
>



-- 
Ray McDermott
GSM 047/32.53.854

Mime
View raw message