About Gal Levinsky

Graduated B.s.c Information System Engineering on BGU University (2004). Been working on large cloud based ERP application in SAP for 7 years and as a development group manager in affiliation company. Co-founded few startups in the domain of social web.

DAO layer – Generics to the rescue

Generics can be a powerful tool to create reusable code with the power of compile time verification (type safety..).

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.

Share and enjoy!


© 2010-2012 Java Code Geeks. Licenced under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.