DAO layer – Generics to the rescue
Unfortunately I feel the main stream developers still afraid of it.
However, in analogy to Hagrid’s spiders I would say that Generics are seriously misunderstood creatures… :-)
I hope the following example will demonstrate how useful they can be.
The Problem – DAO (Data Access Objects) classes have common methods such as save, update, delete, loadAll.. which are required in every DAO class.
Writing a base class with these common methods and making every DAO object extend it, is simply not enough since each DAO class represents a different domain class and therefore the type used in the common methods’ signature is different (although implementation is similar), for example:
class OrderDAO {
//save method receive an Order
public void save(Order order){....}
//getAll method return Orders List
public List<Order> getAll(){...}
}
class UserDAO{
//save method receive an User
public void save(User user){....}
//getAll method return Users List
public List<User> getAll(){...}
}
How Generics can help us create a base class with a common implementation and yet, keep method signature type-safety?
First, we need to define an interface with the common methods:
/**
* Base interface for CRUD operations and common queries
*/
public interface IDaoBase<T> {
public List<T> loadAll();
public void save(T domain);
public void update(T domain);
public void delete(T domain);
public T get(Serializable id);
/**
* Get list by criteria
* @param detachedCriteria the domain query criteria, include condition and the orders.
* @return
*
*/
public List<T> getListByCriteria(DetachedCriteria detachedCriteria);
public List<T> getListByCriteria(DetachedCriteria detachedCriteria, int offset, int size);
}Please note that we utilize generics so each method signature has a type T, which in the implemented DAO classes, will be a concrete type, per domain.
The second step is to create an abstract class which implements the common functionality:
public abstract class DaoBase<T> extends HibernateDaoSupport implements IDaoBase<T> {
private Class<T> entityClass;
@Autowired
public void setSession(SessionFactory sessionFactory){
this.setSessionFactory(sessionFactory);
}
public DaoBase() {
entityClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public List<T> loadAll(){
return getHibernateTemplate().loadAll(entityClass);
}
public void delete(T domain) {
getHibernateTemplate().delete(domain);
}
public void save(T domain) {
getHibernateTemplate().saveOrUpdate(domain);
}
public void update(T domain) {
getHibernateTemplate().merge(domain);
}
public T get(Serializable id) {
T o = (T) getHibernateTemplate().get(entityClass, id);
return o;
}
public List<T> getListByCriteria(DetachedCriteria detachedCriteria,
int offset, int size) {
return getHibernateTemplate().findByCriteria(detachedCriteria, offset, size);
}
public List<T> getListByCriteria(DetachedCriteria detachedCriteria) {
return getHibernateTemplate().findByCriteria(detachedCriteria);
}
}And that’s it !
Take a minute or two to inspect how the base object implements a generic functionality with a type-safety manner.
All we have to do when implementing a new DAO is:
1. Interface to extend the IDaoBase with a concrete type
public interface DaoUser extends IDaoBase<User> {//<=Notice the User typing
//Add any additional custom methods..
public User getbyUsername(String username);
public User getbyEmail(String email);
}
2. Implementation to extend the DaoBase with a concrete type
//This class has all the common methods, which are type safe for the User class
@Repository("daoUser")
public class DaoUserImpl extends DaoBase<User> implements DaoUser { //<=Notice the User typing
public User getbyUsername(String username) {
// concrete implmentation ...
}
So now you see how powerful it is to use generics. Hope it is now a bit less scary and more understood…
Reference: DAO layer – Generics to the rescue from our JCG partner Gal Levinsky at the Gal Levinsky’s blog blog.




