Hello
After quite a lot of different issues with Oracle SQL we have the following workaround for our application.
Hbm.xml mapping example (partial)
Code:
<list name="values" access="field" cascade="all,delete-orphan" table="MSG_MsgProp_Props">
<cache usage="nonstrict-read-write" />
<key column="propertyId"/>
<list-index column="sortOrder"/>
<element type="com.easit.core.hibernate.HibernateString "
column="propValue" length="4096"/>
</list>
As you can see we have a custom class specified for the element data.
HibernateString.java
Code:
public class HibernateString extends StringType {
protected static Dialect dialect;
@Override
public Object get(ResultSet rs, String name)
throws HibernateException, SQLException {
Object value = super.get(rs, name);
if (dialect == null) {
Configuration hibernateConfiguration = BeanUtils.getBean(
"hibernateConfiguration", Configuration.class);
dialect = Dialect .getDialect(hibernateConfiguration.getProperties());
}
if (dialect instanceof Oracle8iDialect) {
if (value == null) {
value = "";
}
}
return value;
}
}
What we want to achieve here is that if we are using Oracle SQL, then we replace null strings with empty strings from the database. The reason is that oracle don’t make any difference between null strings and empty string. Oracle stores null values as “impossible values”, and for some reason an empty string is considered an impossible string value so that is used to represent null. We also use com.google.common.collect.ImmutableList that does not allow null values.
The problem is StringType / NullableType, first of all StringType extends NullableType and nullSafeGet in NullableType is declared as final, the problem arises from the following lines of code in NullableType / nullSafeGet(…).
Code:
Object value = get(rs, name);
if ( value == null || rs.wasNull()) {
if ( IS_VALUE_TRACING_ENABLED ) {
log().trace( "returning null as column: " + name );
}
return null;
}
Even though we overridden ”get(rs, name)” method in our HibernateString class, NullableType checks with rs.wasNull() (that will return true) and nullSafeGet will return null regardless.
We think that overriding the “get(rs, name)” method for the purpose of what we want to achieve is not very useful since it will be ignored later in the Hibernate code.
We haven’t seen any other class to extend apart from StringType. Are there any other class to extend from ?
If not then we think that the design of NullableType / StringType should be changed in some way to allow “rs.notNull()” not to be called.
Hibernate version in use: 3.3.1.GA
// Andreas Hedman