In the hibernate mapping type we found the first approach that is to make the directly implement the org.hibernate.type.Type interface (or one of its derivatives). Specily we have to make the interested in the more specific org.hibernate.type.BasicType contract that will allow registration of the type for this we need to the type registry. The benefit of this registration is that whenever the metadata for a particular property does not specify the Hibernate type to use, Hibernate will consult the registry for the exposed property type. In the below our given program example our property type would be HibernateType, which is the key we would use to register our type in the registry:
Example: Defining and registering the custom Type
public class HibernateType implements BasicType {
public String[] getRegistrationKeys() {
return new String[] { Money.class.getName() };
}
public int[] sqlTypes(Mapping mapping) {
// We will simply use delegation to the standard basic types for BigDecimal and Currency for many of the
// Type methods...
return new int[] {
BigDecimalType.INSTANCE.sqlType(),
CurrencyType.INSTANCE.sqlType(),
};
// we could also have honored any registry overrides via...
//return new int[] {
// mappings.getTypeResolver().basic( BigDecimal.class.getName() ).sqlTypes( mappings )[0],
// mappings.getTypeResolver().basic( Currency.class.getName() ).sqlTypes( mappings )[0]
//};
}
public Class getReturnedClass() {
return HibernateType.class;
}
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {
assert names.length == 2;
BigDecimal amount = BigDecimalType.INSTANCE.get( names[0] ); // already handles null check
Currency currency = CurrencyType.INSTANCE.get( names[1] ); // already handles null check
return amount == null && currency == null
? null
: new HibernateType( amount, currency );
}
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SessionImplementor session)
throws SQLException {
if ( value == null ) {
BigDecimalType.INSTANCE.set( st, null, index );
CurrencyType.INSTANCE.set( st, null, index+1 );
}
else {
final HibernateType money = (HibernateType) value;
BigDecimalType.INSTANCE.set( st, money.getAmount(), index );
CurrencyType.INSTANCE.set( st, money.getCurrency(), index+1 );
}
}
...
}
Configuration cfg = new Configuration();
cfg.registerTypeOverride( new HibernateTypeType() );
cfg...;
It is important that we registered the type before adding mappings.