When you want to use DAO's for your application you will very likely going to use an interface like this:
public interface DAO<T, K extends Serializable> {
T findById(K id);
List<t> list();
void persist(T instance);
void delete(T instance);
}
Using Hibernate for O/R Mapping and Guice as DI framework you can use a sort of template for getting typesafe implementations of DAO's automatically generated for you, and you can ask for them to be injected like this:
public class NeedsDao {
@Inject
public NeedsDao(Dao<MyEntity, Integer> entityDao) {
List<MyEntity> miEntities = entityDao.list();
Entity EntityById = entityDao.findById(3);
}
}
Of course you need to know which type of key you need to use to get your entity, in this case we suppose the key is a plain Integer.
The class that implements the logic for this would be:
public class GenericDAO<T,K> implements DAO<T,K> {
private final Class<T> typeClass;
private final Provider<Session> sessionProvider;
@Inject
public GenericDAO(Provider<Session> sessionProvider, TypeLiteral<T> t) {
this.sessionProvider = sessionProvider;
this.typeClass=(Class<T>)t.getRawType();
}
public List<T> list() {
Session session = sessionProvider.get();
return (List<T>)session.createCriteria(typeClass).list();
}
@SuppressWarnings("unchecked")
@Override
public T findById(K id) {
Session session = sessionProvider.get();
return (T)session.get(typeClass, id);
}
@Override
public void persist(T instance) {
Session session = sessionProvider.get();
session.persist(instance);
}
@Override
public void delete(T instance) {
Session session = sessionProvider.get();
session.delete(instance);
}
}
With this parameterized class we implement all the DAO's we need. We circumvent type erasuring using Guice TypeLiteral injection feature, which allows us for inspecting at runtime which parameter the class has been parameterized with.
Now we only have left to make the wiring in Guice. The easiest way to do this is inspecting Hibernate configuration and generate a binding for each persistent class we have configured. We can write this module:
public class HibernateAutoModule extends AbstractModule {
public HibernateAutoModule(Configuration configuration) {
this.configuration = configuration;
}
@Override
protected void configure() {
configuration.buildMappings();
Iterator<PersistentClass> classMappings = configuration
.getClassMappings();
while (classMappings.hasNext()) {
PersistentClass persistentClass = (PersistentClass) classMappings
.next();
bind(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(
DAO.class, persistentClass.getMappedClass(),
persistentClass.getKey().getType()
.getReturnedClass()))).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(
GenericDAO.class,
persistentClass.getMappedClass(), persistentClass
.getKey().getType().getReturnedClass()))
);
}
}
}
You only need to correctly provide a fresh Configuration object from hibernate and install this module. Note that GenericDAO also depends on you providing a Session object from Hibernate.
Should you want to provide a different implementation for any of the interfaces you can use the Modules.override mechanism from Guice. Just generate a new binding for the interface you want to change the implementation.
I figure that the code won't work for you as is, but I think you can get the idea so you can adapt it for your needs.
Hope this helps!