JPA通用Dao类设计

在上一篇文章中已经配置好struts2+spring+jpa+dwr,这篇我们来讲下通用DAO设计。

设计思路:利用spring对dao层的支持,使用泛行方式对它进行一次包装,此通用DAO只实现最基本的增删改查功能,具体的特殊实现有它的子类实现

接口设计,在原来的工程中建立一个源代码包,名称为common,然后建立包结构,我的包结构如图:

 图片
照片名称:包结构
在dao目录下创建BaseDao.java文件,此文件是一个接口,代码如下:

/**
 * 基本的CRUD实现,使用方式:
 * 比如您有个DAO叫UserDao,那么UserDao的写法如下:
 * UserDao extends BaseDao<Long, User>
 * UserDao的实现类的写法是:
 * UserDaoImpl extends BaseJpaDaoSupport<Long, User> implements UserDao
 * @author HLIN
 *
 * @param <K>
 * @param <V>
 */

public interface BaseDao<K extends Serializable, V> {
   void add(V entity) throws GenericDaoException;
   void delete(V entity) throws GenericDaoException;
   void delete(List<V> entities) throws GenericDaoException;
   void delete(K id) throws GenericDaoException;
   void update(V entity) throws GenericDaoException;
   V find(K id) throws GenericDaoException;
   V findSingle(String hql, Object... params) throws GenericDaoException;
   List<V> find(String ql, Object... params) throws GenericDaoException;
   List<V> findAll() throws GenericDaoException;
   List<V> pageQuery(PageBean pageBean, String hql, Object... params) throws GenericDaoException;

}

这个接口中,我们使用了泛型,第一个参数是表的主键,必须是对象类型的;第二个参数是实体类型,不首限制。

接下来就用hibernate和jpa两种方式实现这个接口

hibernate实现,代码如下:

public class BaseHibernateDaoSupport<K extends Serializable, V> extends
  HibernateDaoSupport implements BaseDao<K, V> {

 public void add(V entity) {
  getHibernateTemplate().save(entity);
 }

 public void delete(V entity) {
  getHibernateTemplate().delete(entity);
 }

 public void delete(List<V> entities) {
  getHibernateTemplate().deleteAll(entities);

 }
 
 public void delete(K id) {
  getHibernateTemplate().delete(find(id));
 }

 @SuppressWarnings("unchecked")
 public V find(K id) {
  return (V) getHibernateTemplate().get(getEntityType(), id);
 }
 
 public V findSingle(final String hql, final Object... params) {
  List<V> list = find(hql, params);
  if (list.size() > 0)
   return list.get(0);
  return null;
 }

 @SuppressWarnings("unchecked")
 public List<V> find(String hql, Object... params) {
  return getHibernateTemplate().find(hql, params);
 }

 public void update(V entity) {
  getHibernateTemplate().update(entity);
 }
 
 @SuppressWarnings("unchecked")
 public List<V> findAll() {
  return getHibernateTemplate().loadAll(getEntityType());
 }

 @SuppressWarnings("unchecked")
 public List<V> pageQuery(final PageBean pageBean, final String hql,
   final Object... params) {
  List<V> list = getHibernateTemplate().executeFind(
    new HibernateCallback() {
     public Object doInHibernate(Session session)
       throws HibernateException, SQLException {
      Query query = session.createQuery(hql);
      for (int i = 0; i < params.length; i++) {
       query.setParameter(i, params[i]);
      }
      return query.setFirstResult(
        (pageBean.getCurrentPage() - 1)
          * pageBean.getPageSize())
        .setMaxResults(pageBean.getPageSize()).list();
     }
    });
  pageBean.setTotalRecords(getRowCount(hql, params));
  return list;
 }

 private Integer getRowCount(String sql, Object... params) {
  sql = "select count(*) " + CommonUtil.removeSelect(CommonUtil.removeOrders(sql));
  return new Integer(findSingle(sql, params).toString());
 }

 @SuppressWarnings("unchecked")
 private Class<V> getEntityType() {
  return (Class<V>) ((ParameterizedType) getClass()
    .getGenericSuperclass()).getActualTypeArguments()[1];
 }

}

然后是JPA的实现,代码如下:

public class BaseJpaDaoSupport<K extends Serializable, V> extends JpaDaoSupport implements BaseDao<K, V> {

 public void add(V entity) {
  getJpaTemplate().persist(entity);
 }

 public void delete(V entity) {
  getJpaTemplate().remove(entity);
 }

 public void delete(List<V> entities) {
  for (V entity : entities)
   getJpaTemplate().remove(entity);
 }

 public void delete(K id) {
  getJpaTemplate().remove(find(id));
 }

 @SuppressWarnings("unchecked")
 public List<V> findAll() {
  String name = getEntityType().getName();
  return getJpaTemplate().find("from " + name.substring(name.lastIndexOf(".")+1));
 }

 public V find(K id) {
  return getJpaTemplate().find(getEntityType(), id);
 }

 @SuppressWarnings("unchecked")
 public List<V> find(String hql, Object... params) {
  return getJpaTemplate().find(hql, params);
 }
 
 @SuppressWarnings("unchecked")
 public V findSingle(final String hql, final Object... params) {
  return (V) getJpaTemplate().execute(new JpaCallback() {
   public Object doInJpa(EntityManager em)
     throws PersistenceException {
    Query query = em.createQuery(hql);
    return query.getSingleResult();
   }
  });
 }

 @SuppressWarnings("unchecked")
 public List<V> pageQuery(final PageBean pageBean, final String hql, final Object... params) {
  return getJpaTemplate().executeFind(new JpaCallback() {
   public Object doInJpa(EntityManager em) throws PersistenceException {
    
    List<V> result = em.createQuery(hql).setFirstResult(
      (pageBean.getCurrentPage() - 1)).setMaxResults(
        pageBean.getPageSize()).getResultList();
    pageBean.setTotalRecords(getRowCount(hql, params));
    return result;
   }

  });
 }

 public void update(V entity) {
  getJpaTemplate().merge(entity);
 }
 
 private Integer getRowCount(String sql, Object... params) {
  sql = "select count(*) " + CommonUtil.removeSelect(CommonUtil.removeOrders(sql));
  return new Integer(findSingle(sql, params).toString());
 }

 @SuppressWarnings("unchecked")
 private Class<V> getEntityType() {
  return (Class<V>) ((ParameterizedType) getClass()
    .getGenericSuperclass()).getActualTypeArguments()[1];
 }

}

好了,大功告成,我们来写个单元测试一下,这里的测试类使用的是spring的mock包,可以大大简化我们的spring测试

首先写一个测试基类,名称为BaseTestCase,代码如下:

public class BaseTestCase extends AbstractDependencyInjectionSpringContextTests {

 protected String[] getConfigLocations() {
  return new String[]{"classpath:spring-main.xml"};
 }

}

这里继承的基类是AbstractDependencyInjectionSpringContextTests ,如果是在实际运行系统中测试,则需要继承AbstractTransactionalSpringContextTests,代码如下:

public class BaseTestCase extends AbstractDependencyInjectionSpringContextTests {

 protected String[] getConfigLocations() {
  return new String[]{"classpath:spring-main.xml"};
 }

}

你可能感兴趣的:(JPA通用Dao类设计)