基于Spring、Hibernate实现通用Dao层

基于Spring、Hibernate实现通用Dao层

这两天又捡起来老司机的web端代码,需要增加一些新的功能,比如说充值卡(PrepaidCard)模块。在写Dao层的时候发现好麻烦呀,每个实体类都要写一个对应的Dao(还包括接口跟实现),而大部分Dao方法都是基本的增删查改操作(CRUD)。比如getById,save,update,count,query,delete。而这些基本操作的代码其实都是相差无几的,既然这样那我们是不是可以写一个BaseDao来实现基本操作,然后让其他Dao来继承他。

以我现在要写的PrepaidCard实体类为例:

/**
 * 省略各种import
**/

@Entity
@Table(name = "fp_prepaid_card")
public class PrepaidCard implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name = "id")
    @Id
    @GeneratedValue
    private long id;

    @Column(name = "token", unique = true, length = 36, nullable = false)
    private String token;

    @Column(name = "days")
    private long days;

    @Column(name = "created_time", columnDefinition = "DATETIME", nullable = false)
    private Date createdTime;

    @Column(name = "used_time", columnDefinition = "DATETIME", nullable = false)
    private Date usedTime;

    @JoinColumn(name = "consumer_id", referencedColumnName = "id")
    @ManyToOne(targetEntity = User.class, fetch = FetchType.EAGER, cascade = {})
    private User user;
    
    /**
     * 省略各种方法
    **/
}

1、没有实现BaseDao时候的PrepaidCardDao

package com.funway.fproxy.dao;

import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import com.funway.fproxy.domain.PrepaidCard;

public interface PrepaidCardDao {
    
    /**
     * 根据序列号获取充值卡
     * @param token
     * @return
     */
    PrepaidCard getPrepadiCardByToken(String token);
    
    /**
     * 保存充值卡信息
     * 对应sql语句是insert,会立即执行
     * @param prepaidCard
     */
    void save(PrepaidCard prepaidCard);
    
    /**
     * 更新充值卡信息
     * 对应sql语句是update,不会立即执行,等待flush
     * @param prepaidCard
     */
    void update(PrepaidCard prepaidCard);
    
    /**
     * 按条件统计
     * @param deCriteria
     * @return
     */
    long count(DetachedCriteria deCriteria);
    
    /**
     * 按条件查询,不支持分页
     * @param deCriteria 查询条件
     * @return
     */
    List<PrepaidCard> query(DetachedCriteria deCriteria);
    
    /**
     * 按条件查询,支持分页
     * @param deCriteria 查询条件
     * @param page 第几页(从1开始;负数或0时page等效于1)
     * @param pageSize 每页行数(负数或0时pageSize无效,取所有行)
     * @return
     */
    List<PrepaidCard> query(DetachedCriteria deCriteria, int page, int pageSize);
}

 
package com.funway.fproxy.dao.impl;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.funway.fproxy.dao.PrepaidCardDao;
import com.funway.fproxy.domain.PrepaidCard;

@Repository
public class PrepadiCardDaoImpl implements PrepaidCardDao {
    
    @Autowired
    private SessionFactory sessionFactory;
    
    @Override
    public PrepaidCard getPrepadiCardByToken(String token) {
        String hqlQueryString = "from PrepaidCard as pc where pc.token = :token";
        Session session = sessionFactory.openSession();
        
        try {
            Query query = session.createQuery(hqlQueryString).setString("token", token);
            PrepaidCard prepaidCard = (PrepaidCard) query.uniqueResult();
            return prepaidCard;
        } finally {
            session.close();
        }
    }

    @Override
    public void save(PrepaidCard prepaidCard) {
        Session session = sessionFactory.getCurrentSession();
        session.save(prepaidCard);
    }

    @Override
    public void update(PrepaidCard prepaidCard) {
        Session session = sessionFactory.getCurrentSession();
        session.update(prepaidCard);
    }

    @Override
    public long count(DetachedCriteria deCriteria) {
        Session session = sessionFactory.openSession();
        try {
            deCriteria.setProjection(Projections.rowCount());
            long count = (long) deCriteria.getExecutableCriteria(session).uniqueResult();
            return count;
        } finally {
            session.close();
        }
    }

    @Override
    public List<PrepaidCard> query(DetachedCriteria deCriteria) {
        return query(deCriteria, 1, 0);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<PrepaidCard> query(DetachedCriteria deCriteria, int page, int pageSize) {
        Session session = sessionFactory.openSession();
        try {
            Criteria criteria = deCriteria.getExecutableCriteria(session);
            criteria.setFirstResult((page - 1) * pageSize);
            criteria.setMaxResults(pageSize);
            List<PrepaidCard> prepaidCards = criteria.list();
            return prepaidCards;
        } finally {
            session.close();
        }
    }
}

2、实现BaseDao

我们在BaseDao中只定义了常用的CRUD操作,子类可以重写,或者新增自己特定的方法。

package com.funway.fproxy.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;

public interface BaseDao<T> {

    /**
     * 保存实体
     * 对应sql为insert,立即执行
     * @param entity
     */
    public void save(T entity);
    
    /**
     * 更新实体
     * 对应sql为update,不立即执行,等待flush
     * @param entity
     */
    public void update(T entity);
    
    /**
     * 删除实体
     * @param entity
     */
    public void delete(T entity);
    
    /**
     * 根据主键查找实体
     * @param id
     * @return
     */
    public T getById(Serializable id);
    
    /**
     * 按条件统计
     * @param deCriteria
     * @return
     */
    public long count(DetachedCriteria deCriteria);
    
    /**
     * 按条件查询,不支持分页
     * @param deCriteria 查询条件
     * @return
     */
    public List<T> query(DetachedCriteria deCriteria);
    
    /**
     * 按条件查询,支持分页
     * 
     * @param deCriteria
     *            查询条件
     * @param page
     *            第几页(从1开始;负数或0时page等效于1)
     * @param pageSize
     *            每页行数(负数或0时pageSize无效,取所有行)
     * @return
     */
    public List<T> query(DetachedCriteria deCriteria, int page, int pageSize);
}

 
package com.funway.fproxy.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;

import com.funway.fproxy.dao.BaseDao;

@SuppressWarnings("unchecked")
public class BaseDaoImpl<T> implements BaseDao<T> {

    @Autowired
    protected SessionFactory sessionFactory;

    /**
     * 泛型T的实际类型
     */
    private Class<T> entityClass;

    public BaseDaoImpl() {
        // 获得泛型T的实际类型
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<T>) type.getActualTypeArguments()[0];
//        System.out.println("实体类型: " + this.entityClass.getName());
    }

    @Override
    public void save(T entity) {
        Session session = sessionFactory.getCurrentSession();
        session.save(entity);
    }

    @Override
    public void update(T entity) {
        Session session = sessionFactory.getCurrentSession();
        session.update(entity);
    }

    @Override
    public void delete(T entity) {
        Session session = sessionFactory.getCurrentSession();
        session.delete(entity);
    }

    @Override
    public T getById(Serializable id) {
        Session session = sessionFactory.openSession();
        try {
            T result = (T) session.get(entityClass, id);
            return result;
        } finally {
            session.close();
        }
    }

    @Override
    public long count(DetachedCriteria deCriteria) {
        Session session = sessionFactory.openSession();
        try {
            deCriteria.setProjection(Projections.rowCount());
            long count = (long) deCriteria.getExecutableCriteria(session).uniqueResult();
            return count;
        } finally {
            session.close();
        }
    }

    @Override
    public List<T> query(DetachedCriteria deCriteria) {
        return query(deCriteria, 1, 0);
    }

    @Override
    public List<T> query(DetachedCriteria deCriteria, int page, int pageSize) {
        Session session = sessionFactory.openSession();
        try {
            Criteria criteria = deCriteria.getExecutableCriteria(session);
            criteria.setFirstResult((page - 1) * pageSize);
            criteria.setMaxResults(pageSize);
            List<T> entities = criteria.list();
            return entities;
        } finally {
            session.close();
        }
    }

}

3、继承了BaseDao的PrepaidCardDao

修改我们之前写的PrepaidCardDao/PrepaidCardDaoImpl代码,通过继承BaseDao来获得通用的CRUD方法。

package com.funway.fproxy.dao;

import com.funway.fproxy.domain.PrepaidCard;

public interface PrepaidCardDao extends BaseDao<PrepaidCard> {

    /**
     * 根据序列号获取充值卡
     * @param token
     * @return
     */
    PrepaidCard getPrepadiCardByToken(String token);
}

package com.funway.fproxy.dao.impl;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Repository;

import com.funway.fproxy.dao.PrepaidCardDao;
import com.funway.fproxy.domain.PrepaidCard;

@Repository
public class PrepaidCardDaoImpl extends BaseDaoImpl<PrepaidCard> implements PrepaidCardDao {

    @Override
    public PrepaidCard getPrepadiCardByToken(String token) {
        String hqlQueryString = "from PrepaidCard as pc where pc.token = :token";
        Session session = sessionFactory.openSession();

        try {
            Query query = session.createQuery(hqlQueryString).setString("token", token);
            PrepaidCard prepaidCard = (PrepaidCard) query.uniqueResult();
            return prepaidCard;
        } finally {
            session.close();
        }
    }
}

 

 

参考:

http://1194867672-qq-com.iteye.com/blog/1159918

发表评论

电子邮件地址不会被公开。 必填项已用*标注