Write an Interceptor that calls a different constructor for Hibernate. For example, add a Constructor like this to your business object:
Code:
public Campus( Serializable id, byte ignore ) {
setId( (Long)id );
}
I added a byte param to the constructor to make it less likely that it would conflict with or be confused with something like Campus(String campusName). Now here's an Interceptor that I wrote that will always use that constructor when Hibernate loads objects from the database:
Code:
public class HibernateConstructorInterceptor extends EmptyInterceptor {
private static final Byte fakeParam = new Byte((byte)0);
private static final Class[] HIBERNATE_SIGNATURE = new Class[] {Serializable.class, byte.class};
private Map constructors = new HashMap(30);
public Object instantiate( String entityName, EntityMode entityMode, Serializable id ) {
if( entityMode != EntityMode.POJO ) return null; //Don't know how to deal with other entity types
Object cachedValue = constructors.get( entityName );
if( cachedValue == fakeParam ) return null; //We've already checked, and there's no Hibernate constructor
try {
Constructor constructor;
if( cachedValue != null ) {
constructor = (Constructor)cachedValue; //Found the constructor in the cache
} else {
Class entityClass = Class.forName( entityName ); //Not sure whether this is the safest way to get the class, there might be a better alternative.
try {
constructor = entityClass.getConstructor( HIBERNATE_SIGNATURE );
constructors.put( entityName, constructor ); //Found it! Store it in the cache for next time.
} catch( NoSuchMethodException e ) {
constructors.put( entityName, fakeParam ); //No Hibernate constructor. Remember for next time to save the time to check.
return null;
}
}
return constructor.newInstance( new Object[] {id, fakeParam} ); //Call Hibernate constructor with id.
} catch( Exception e ) {
e.printStackTrace();
return null;
}
}
}
Now you can put your 'real' business logic in the constructor, knowing that it will only be triggered when you explicitly call it. If you don't create a constructor with that specialized signature, the regular no-arg one will be used.