Session Bean Hi/Lo GeneratorThe hi/lo identifier generator built into Hibernate does not work with container managed transactions. However, its easy enough to wrap it up in a session bean. Heres a possible implementation using XDoclet:
/**
* @ejb.bean name="HiLoGenerator"
* jndi-name="hibernate/HiLoGenerator"
* type="Stateless"
* display-name="Hi/Lo Generator"
* description="Hibernate Hi/Lo Generator Session Bean"
*
* @ejb.transaction type="NotSupported"
*/
public abstract class HiLoGeneratorBean implements SessionBean {
// Use the built-in Hibernate hi/lo generator:
IdentifierGenerator gen = new HiLoGenerator();
/**
* @ejb.interface-method
*/
public Long next() throws HibernateException {
try {
return (Long) gen.generate( getSession(), null );
}
catch (SQLException sqle) {
throw new IdentifierGenerationException( "SQLException: " + sqle.getMessage() );
}
}
/**
* @ejb.create-method
*/
public void ejbCreate() throws CreateException {
}
private SessionImplementor getSession() throws HibernateException, SQLException {
// get a new Hibernate session and cast to SessionImplementor
// actually, we only need it for its JDBC connection
.....
}
}
This implementation ensures that the enclosing container transaction is suspended before generating the next identifier. The following class implements the Hibernate IdentifierGenerator interface and delegates to the session bean. You should specify this class in the <generator> element.
public class SessionBeanHiLoGenerator implements IdentifierGenerator {
public Serializable generate(SessionImplementor session, Object object)
throws HibernateException {
try {
return HiLoGeneratorUtil.getHome().create().next();
}
catch (Exception e) {
throw new IdentifierGenerationException( "Could not generate id: " + e.getMessage() );
}
}
}
Notice how much less readable this code example would be if we weren't using XDoclet!
|