Hi,
In an attempt to create a reusable hibernate project within eclipse on a common database schema used across multiple development projects, I wanted to create hibernate mappings for interfaces with default implementations for those interfaces provided within that project. If a subsequent projects required a different implementation of the interface, it could easily be swapped out by modifying my interface to implementation mapping configuration singleton (accesed through spring). Everything seemed to work great when I added an interceptor to the hibernate configuration, however I ran across a case where the interceptor wasn't being fired at all, and instead the interface is being extended by cglib instead of the implementation class as in other cases. After spending a few days on this, I would like to ask the experts here at the boards for help as I have not been able to figure out how to resolve it.
The interceptor works well where new instances of the objects directly and collections of instances are created through lazy instantiation. However, when I used a <many-to-one> mapping with a foreign key, the interceptor isn't being fired at all.
One other alternative that I tried was to use a LoadEventListener instead and set the event.setInstanceToLoad(Object o) to be a new instance of the implementing class, however in that case I ended up getting a NonUniqueObjectException.
Any help would be greatly appreciated as my deadline is approaching fast and I'm running out of options.
Below is my code:
MyConfiguration interceptor setting:
Code:
configuration = new Configuration().configure();
configuration.setInterceptor(new InterfaceInterceptor());
InterfaceInterceptor
Code:
public class InterfaceInterceptor extends EmptyInterceptor {
public String getEntityName(Object object) {
MyConfiguration config = (MyConfiguration)Lookup.getBean("myConfig");
for(Class<?> cl : config.getInterfaces()){
if(cl.isAssignableFrom(object.getClass())){
return cl.getName();
}
}
return super.getEntityName(object);
}
public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
MyConfiguration config = (MyConfiguration)Lookup.getBean("myConfig");
Class<? extends BeanWithId> interfaceClass = config.getEntityName(entityName);
if(interfaceClass != null){
Class<? extends BeanWithId> instantiationClass = config.getInstantiatingClass(interfaceClass);
try {
BeanWithId bean = instantiationClass.newInstance();
bean.setId((Integer)id);
return bean;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return super.instantiate(entityName, entityMode, id);
}
}
LoadEventListener
Code:
public class LoadListener implements LoadEventListener {
public void onLoad(LoadEvent event, LoadType loadType) throws HibernateException {
if(event.getInstanceToLoad() == null){
MyConfiguration config = (MyConfiguration)Lookup.getBean("myConfig");
Class<? extends BeanWithId> interfaceClass = config.getEntityName(event.getEntityClassName());
if(interfaceClass != null){
Class<? extends BeanWithId> instantiationClass = config.getInstantiatingClass(interfaceClass);
try {
BeanWithId bean = instantiationClass.newInstance();
bean.setId((Integer)event.getEntityId());
event.setInstanceToLoad(bean);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
mapping file that caused the problem.
Code:
<hibernate-mapping package="my.hibernate.mapping">
<class name="TaskIntf" table="Task">
<id name="Id" type="integer">
<generator class="native" />
</id>
<many-to-one name="Content" column="content" class="ContentIntf"/>
</class>
</hibernate-mapping>
Thanks,
Richard