I am trying to write a Generic Data Access Layer for my application. I have multiples hibernate entities which are mostly the same and are represented as a class hierarchy in Java (they are not implemented as a hierarchy in Hibernate) :
public abstract class Entity1 {
// some implementation
}
public class Entity2 extends Entity1 {
// some implementation
}
public class Entity3 extends Entity1 {
// some implementation
}
The DAOs for those entities are mostly the same (except for the type signature of the methods, and the class asked to Hibernate). I would like to be able to write a generic DAO like this :
public interface EntityDao<T extends Entity1> {
List<T>getEntities();
void saveOrUpdateEntity(T entity);
}
public class EntityDaoImpl implements EntityDao<Entity1> {
private final HibernateTemplate hibernateTemplate;
private final Class<DBEnumerationDto> clazz;
public DBEnumerationDaoHibernateImpl(SessionFactory sessionFactory, Class<DBEnumerationDto> clazz) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
this.clazz = clazz;
}
@Override
public List<Entity1> getEntities() {
return this.hibernateTemplate.loadAll(this.clazz);
}
@Override
public void saveOrUpdateEntity(Entity1 entity) {
this.hibernateTemplate.saveOrUpdate(entity);
}
}
So far, so good. But the problem arises when using this :
Entity1 test = new Entity1();
Entity1Dao<? extends Entity1> dao = ...; // get the dao forthe current operation
dao.saveOrUpdate(test);
This gives a compiler error : The method saveOrUpdateEntity(capture#5-of ? extends Entity1) in the type EntityDao<capture#5-of ? extends Entity1> is not applicable for the arguments (Entity1)
I guess this question relates to http://stackoverflow.com/questions/1375718/java-generics-casting-to-or-a-way-to-use-an-arbitrary-foo but I cant really grasp in which way.
How should I fix my code ? Or is my approach wrong ?