通过泛型实现持久层 BaseDao 的写法

问题说明:我们在编写 Dao 层的时候,总会遇到通用的增删改查方法,每一次都要写声明和实现是一件很繁琐的事情,而且代码有很多事相同点。于是我们想到了使用面向对象的三大特性和泛型语法来简化持久层的开发。

Base 的实现类和接口都是抽象的,所以都带泛型。

第 1 步:编写 BaseDao 接口 IBaseDao

注意泛型。

public interface IBaseDao<T> {
    public void add(T t);
    public void delete(Integer id);
    public void update(T t);
    public T load(Integer id);
    public T get(Integer id);
    public List<T> list(String hql, Object[] params);
}

说明:这个接口是一个高度抽象的接口。每个实体类都会有这样的方法。
既然有基本接口类,那么就会有基本实现类。

第 2 步:编写基本实现类 BaseDao

说明:下面的代码中继承 HibernateDaoSupport 非必需,根据我们选择不同的持久层框架而定,例子中的代码选择的是 Hibernate 持久层框架。

/**
 * Created by Liwei on 2016/5/6.
 */
public class BaseDao<T> extends HibernateDaoSupport implements IBaseDao<T>{

    @Resource(name = "sessionFactory")
    public void setSuperSessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);

    }

    public void add(T t) {
        getHibernateTemplate().save(t);
    }

    public void delete(Integer id) {
        getHibernateTemplate().delete(this.load(id));
    }

    public void update(T t) {
        getHibernateTemplate().update(t);
    }

    /**
     * 创建一个 Class 的对象来获取泛型的 Class
     */
    private Class<T> clz;


    public Class<T> getClz(){
        if(clz==null){
            clz = ((Class<T>)(((ParameterizedType)(this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]));
        }
        return clz;
    }


    /**
     *
     * @param id
     * @return
     */
    public T load(Integer id) {
        return getHibernateTemplate().load(getClz(),id);
    }

    public T get(Integer id) {
        return getHibernateTemplate().get(getClz(),id);
    }

    /**
     *
     * @param hql
     * @param params
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<T> list(String hql, Object[] params) {
        Query query = this.getSession().createQuery(hql);
        for(int i=0;i>params.length;i++){
            query.setParameter(i,params[i]);

        }
        List<T> list = query.list();
        return list;
    }
}

第 3 步:编写具体接口

关键点:接口继承接口,但被继承的接口应该写上实现类了。

public interface IUserDao extends IBaseDao<User> {

    public void add(User user, Integer groupid);
}

第 4 步:编写实现类

@Repository
public class UserHibernateDao extends BaseDao<User> implements IUserDao{

    private IGroupDao groupHibernateDao;

    public IGroupDao getGroupHibernateDao() {
        return groupHibernateDao;
    }

    @Autowired
    public void setGroupHibernateDao(IGroupDao groupHibernateDao) {
        this.groupHibernateDao = groupHibernateDao;
    }

    public void add(User user, Integer groupid) {
        Group group = groupHibernateDao.load(groupid);
        user.setGroup(group);
        this.getHibernateTemplate().save(user);
    }
}