这两天又捡起来老司机的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(); } } }
参考: