related JIRA: HB-313
I'd like to be able to map a Character enum to a column which allows nulls. However, the set method in CharacterType behaves differently than the one in StringType:
CharacterType set method:
Code:
public void set(PreparedStatement st, Object value, int index) throws SQLException {
st.setString( index, (value).toString() );
}
StringType set method:Code:
public void set(PreparedStatement st, Object value, int index) throws SQLException {
st.setString(index, (String) value);
}
Why can't CharacterType set method simply allow nulls to be set, too?something like:
Code:
st.setString( index, [b]value == null ? null : (value).toString()
I was forced to use a String identifier instead of Character in my enum domain class
Although HB-313 was rejected, it seems that there are other reasons why CharacterString should allow nulls.
Hibernate version: 3.2.3.ga Mapping documents:Quote:
<hibernate-mapping>
...
<typedef name="YesNoUnknown" class="com....hibernate.GenericEnumUserType">
<param name="enumClass">com.....enums.YesNoUnknown</param>
<param name="identifierMethod">getAbbr</param>
<param name="valueOfMethod">getYesNoFromAbbreviation</param>
</typedef>
...
<class name="com....UserProfile" ...>
...
<property name="agreedToCreditCheck" type="YesNoUnknown">
<column name="AGREED_TO_CREDIT_CHECK" length="2"/>
</property>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close(): Transaction txn = sessionFactory.getCurrentSession().beginTransaction();
UserProfile profile =
makeStandardTestProfile(...);
helper.save(profile);
txn.commit();
relevant snippet Hibernate 3 Parameterized type for mapping a Java 5 Enum. GenericUserType Code:
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
try {
if (value == null) {
st.setNull(index, type.sqlType());
} else {
Object identifier = identifierMethod.invoke(value, new Object[0]);
type.set(st, identifier, index);
}
} catch (Exception e) {
throw new HibernateException("Exception while invoking identifierMethod '"
+ identifierMethod.getName() + "' of " + "enumeration class '" + enumClass + "'", e);
}
}
Full stack trace of any exception that occurs:Quote:
org.hibernate.HibernateException: Exception while invoking identifierMethod 'getAbbr' of enumeration class 'class com.....YesNoUnknown'
at com.....hibernate.GenericEnumUserType.nullSafeSet(GenericEnumUserType.java:103)
at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:146)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:1997)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2371)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at com.....UserProfileDBTest.saveStandardTestProfile(UserProfileDBTest.java:205)
at com.....UserProfileDBTest.testNull(UserProfileDBTest.java:103)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
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 org.hibernate.type.CharacterType.set(CharacterType.java:42)
at com.....GenericEnumUserType.nullSafeSet(GenericEnumUserType.java:100)
... 36 more
Name and version of the database you are using:
Oracle
The generated SQL (show_sql=true):
Debug level Hibernate log excerpt: