We strongly type the IDs of our persistent objects so that when we reference objects by ID, we know which kind of object we're dealing with. This makes things more readable, improves type safety, etc.
We want to use a Hibernate ID sequence generator that maps database NUMBERs to custom types, in particular subclasses of our PersistentEntityId class, rather than to Long, Integer, or Short. We couldn't figure out a way to do this out-of-the box (please correct me if I'm wrong), so we copied-and-modified Hibernate's SequenceGenerator to come up with our own IdSequenceGenerator.
I posted the results below too see if are interested in this pattern. I suspect that Hibernate's built-in ID generators could easily be extended to map to custom types, so I'll file an enhancement request if there's sufficient interest.
Sample mapping:
Code:
<!-- primary key -->
<id name="id"
column="NODE_ID"
type="com.purisma.node.NodeId">
<generator class="com.purisma.db.util.IdSequenceGenerator">
<param name="sequence">NODE_SEQ</param>
</generator>
</id>
IdSequenceGenerator class:
Code:
public class IdSequenceGenerator implements IdentifierGenerator, Configurable
{
public static final String HIBERNATE_SEQUENCE = "hibernate_sequence";
public static final String SCHEMA = "schema";
public static final String SEQUENCE = "sequence";
private Class _idClass = null;
private String _sequenceName = null;
private Type _type = null;
private String _nextValSql = null;
public void configure(Type type, Properties params, Dialect dialect)
throws MappingException {
// get the name of the sequence
_sequenceName = PropertiesHelper.getString(SEQUENCE, params, HIBERNATE_SEQUENCE);
String schemaName = params.getProperty(SCHEMA);
if ( schemaName!=null && _sequenceName.indexOf(StringHelper.DOT)<0 )
_sequenceName = schemaName + '.' + _sequenceName;
_nextValSql = dialect.getSequenceNextValString(_sequenceName);
// verify the validity of the ID type
_type = type;
_idClass = type.getReturnedClass();
if (! PersistentEntityId.class.isAssignableFrom(_idClass)) {
throw new MappingException("ID class does not extend PersistentEntityId: " + _idClass);
}
}
public Serializable generate(SessionImplementor session, Object obj)
throws SQLException, HibernateException
{
PreparedStatement st = session.getBatcher().prepareStatement(_nextValSql);
try {
ResultSet rs = st.executeQuery();
final long result;
try {
rs.next();
result = rs.getLong(1);
} finally {
rs.close();
}
return PersistentEntityId.createIdObject(_idClass, result);
} catch (SQLException sqle) {
JDBCExceptionReporter.logExceptions(sqle);
throw sqle;
} finally {
session.getBatcher().closeStatement(st);
}
}
}
p.s. We have developed a good deal of Hibernate "how to" documentation to help our engineers understand and use Hibernate. I'd like to offer this back to the community as well -- should I post it to the Community wiki?