public interface GenericDao<T> { public void save(T entity); public void update(T entity); public T find(Serializable entityId); public void delete(Serializable... ids); }
Step 2: Create an abstract GenericDaoSupport Class
@SuppressWarnings("unchecked") public abstract class GenericDaoSupport<T> implements GenericDao<T> { private Class<T> entityClass = GenericsUtils.getSuperClassGenericType (this.getClass()); @PersistenceContext(unitName="ejbPU") protected EntityManager em; public void delete(Serializable... ids) { for(Serializable id: ids){ em.remove(em.getReference(entityClass, id)); } } public T find(Serializable entityId) { return em.find(entityClass, entityId); } public void save(T entity) { em.persist(entity); } public void update(T entity) { em.merge(entity); } }
We need a utility class here to get the entity type
e.g. For GenericDaoSupport<Order>,
GenericsUtils.getSuperClassGenericType() will return Order class
public class GenericsUtils { @SuppressWarnings("unchecked") public static Class getSuperClassGenericType(Class clazz){ return getSuperClassGenericType(clazz, 0); } /** * * @param clazz * @param index * @return */ @SuppressWarnings("unchecked") public static Class getSuperClassGenericType (Class clazz, int index){ //Get super class's generic Type //e.g. GenericDaoSupport<Order> Type genericType = clazz.getGenericSuperclass(); //If not a parameterized type, e.g. GenericDaoSupport if (!(genericType instanceof ParameterizedType)){ //Just return the Object class return Object.class; } //Get actual types //e.g. for GenericDaoSupport<Order, Customer, Item> //params = {Order, Customer, Item} Type[] params = ((ParameterizedType)genericType) .getActualTypeArguments(); if (index >= params.length || index < 0){ throw new IllegalArgumentException ("The index is invalid:"+index); } return (Class)params[index]; } }
Step 3: Create an entity
@Entity @Table(name="T_ORDER") public class Order implements Serializable{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; @Column(name="CREATE_DATE") @Temporal(TemporalType.DATE) private Date createDate = new Date(); public int getId() { return id; } public Date getCreateDate() { return createDate; } }
Step 4: Declare an enity Dao interface
public interface OrderDao extends GenericDao<Order> { }
Step 5: Implement the entity Dao interface
@Stateless(name="orderDao") @Remote(OrderDao.class) public class OrderDaoImpl extends GenericDaoSupport<Order> implements OrderDao { }
So whenever we need to create a new entity Dao, we just need to have it extend GenericDaoSupport so that we don't have to duplicate the code of CRUD operations.