One thing that annoys me the most is code duplication. The DAO layer is the perfect candidate for this kind of situation. Often, developers forget about OOP, polymorphism, and design patterns and just copy and paste code, change the name of the class, and voila, we have a brand “new” BankDao
class. I’ll present you how to implement a generic DAO pattern to avoid code duplication and preserve type safety at the same time. Why would you care about type safety and just not use EntityManager
’s generic methods. Well, for various reasons:
- You know for sure which entity objects can be persisted
- You avoid a lot of explicit casts which are error prone
- The code is cleaner and very easy to follow
- You actually apply OOP principles like inheritance and polymorphism
The purpose of this article is not to get you familiar with the DAO pattern, but to show you a better way of using it. You can find a complete reference about DAO here: DataAccessobject.
The Generic DAO Interface
Let’s get started. First of all, this article assumes you are using Spring 3 (although this can be easily adapted to Spring 2.5) and JPA 2.0 in your project and the initial configuration is in place: you already have a data source declared, an entity manager factory, etc. The application is basically up and running.
The foundation of using a Generic DAO is the CRUD operations that you can perform on each entity. And this is the least you can have. Additional generic methods can be defined like: count all objects of a specific type, execute generic queries based on some parameters, etc. You’ll see a sample bellow for countAll()
.
The core of this pattern will be an interface called, surprisingly, GenericDao
and its implementation GenericDaoImpl
. This is the code:
package insidecoding.javaee.dao
import java.util.List;
import java.util.Map;
public interface GenericDao<T> {
long countAll(Map<String, Object> params);
T create(T t);
void delete(Object id);
T find(Object id);
T update(T t);
}
The Generic DAO Implementation
package insidecoding.javaee.dao.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import insidecoding.javaee.dao.GenericDao;
public abstract class GenericDaoImpl<T> implements GenericDao<T> {
@PersistenceContext
protected EntityManager em;
private Class<T> type;
public GenericDaoImpl() {
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
type = (Class) pt.getActualTypeArguments()[0];
}
@Override
public long countAll(final Map<String, Object> params) {
final StringBuffer queryString = new StringBuffer(
"SELECT count(o) from ");
queryString.append(type.getSimpleName()).append(" o ");
queryString.append(this.getQueryClauses(params, null));
final Query query = this.em.createQuery(queryString.toString());
return (Long) query.getSingleResult();
}
@Override
public T create(final T t) {
this.em.persist(t);
return t;
}
@Override
public void delete(final Object id) {
this.em.remove(this.em.getReference(type, id));
}
@Override
public T find(final Object id) {
return (T) this.em.find(type, id);
}
@Override
public T update(final T t) {
return this.em.merge(t);
}
}
This class offers CRUD operations for a generic type T
. The class is marked as abstract
so it can be used only through specific entity DAO implementations. Nothing spectacular about this class, except one thing: the constructor. This is where all the magic will happen. In order to keep things as clean as possible and to avoid AOP and other techniques, we use this hack: we get the actual parametrized type of a concrete class, store it in a Class
variable, and use it in EntityManager
’s methods. Reflection rulz!
Writing Concrete DAOs
Writing concrete DAOs is a piece of cake. A step-by-step overview will be as follows:
- Create a specific entity interface that extends
GenericDao
. - Create a concrete implementation of the above
interface
that extends GenericDaoImpl
and implements the above interface
.
Suppose we have a User
entity and we want to create a UserDao
. We’ll have:
package insidecoding.javaee.dao;
import insidecoding.javaee.model.User;
public interface UserDao extends GenericDao<User> {
public User loadUserByUsername(String username);
}
---------------------------------------------------------------
package insidecoding.javaee.dao.impl;
import java.util.List;
import javax.persistence.Query;
import org.springframework.stereotype.Component;
import insidecoding.javaee.dao.UserDao;
import insidecoding.javaee.model.User;
@Component("userDao")
public class UserDaoImpl extends GenericDaoImpl<User> implements UserDao {
public User loadUserByUsername(String username) {
Query query = this.em
.createQuery("select u FROM User u where u.username= :username");
query.setParameter("username", username);
List<User> users = query.getResultList();
if (users != null && users.size() == 1) {
return users.get(0);
}
return null;
}
}
A concrete entity DAO class will extend GenericDaoImpl<Entity>
and add additional methods if needed. If you don’t need additional methods, this will be just:
package insidecoding.javaee.dao;
import insidecoding.javaee.model.User;
public interface UserDao extends GenericDao<User> {
}
---------------------------------------------------------------
package insidecoding.javaee.dao.impl;
import org.springframework.stereotype.Component;
import insidecoding.javaee.dao.UserDao;
import insidecoding.javaee.model.User;
@Component("userDao")
public class UserDaoImpl extends GenericDaoImpl<User> implements UserDao {
}
Dead simple. As we used the @Component
annotation, you don’t even need to do additional Spring configuration. Just inject the UserDao
and call the available methods. A typical usage will look like this:
package insidecoding.javaee.service.impl;
import org.springframework.transaction.annotation.Transactional;
public interface UserService {
@Transactional
void createUser(String uname, String upwd);
}
---------------------------------------------------------------
package insidecoding.javaee.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import insidecoding.javaee.dao.UserDao;
import insidecoding.javaee.model.User;
import insidecoding.javaee.service.UserService;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao dao;
@Override
public void createUser(String uname, String upwd) {
User u = new User();
u.setUsername(uname);
u.setPassword(upwd);
dao.create(u);
}
}
UserDao
will expect a User
object as parameter, just as we intended. Same thing for the rest of the methods. With just a few lines of code (just the class
and interface
declarations), we’ve achieved a type safety way to interact with our domain model.
If you have Spring configured to user annotations, the above code can just be dropped into your project and you can start using and extending it immediately.
Prior to Java 5, this was impossible. Now that we have Generics, it’s a shame not to use its power.
If you have any questions, please leave a comment below.