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:
01 02 03 04 05 06 07 08 09 10 11 12 13 | 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:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /** * 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:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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
1 2 3 4 5 | 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
1 2 3 4 5 6 7 | //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.