既然Hibernate 实现了对JDBC的轻量级封装,增加了可移植性,那么在CRUD操作上是否也可将起封装,增加其扩展性。答案肯定是可以的。所以就有了今天的基于泛型DAO,网上有很多是在Spring 和 Hibernate 混合框架的泛型DAO,其实就是Spring 在对 Hibernate 的Session 做了一个封装,此博文是针对以Hibernate框架的泛型DAO设计。
由于我们通常要读取hibernate.cfg.xml,创建一个session factory,在取出一个session 对其进行CRUD操作,所以,这部分代码一般可以写在static块中,但为了模块化,我们将其中写在一个单独的类HibernateUtil(官方建议)中。
package com.feytuo.education.persistence; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.tool.hbm2ddl.SchemaExport; /** * 获取会话HibernateUtil封装类 * * @author YangKang * * @date 2014/04/27 * * @version 1.0 * * */ public class HibernateUtil { private static SessionFactory sessionFactory = null; /** * * @return 获取当前会话工厂 */ public static SessionFactory getSessionFactory() { if (null == sessionFactory) { CreateSessionFactory(); } return sessionFactory; } /** * 创建会话工厂 */ private static void CreateSessionFactory() { // 第一步:读取Hibernate的配置文件 hibernamte.cfg.xml文件 Configuration config = new Configuration().configure(); // 第二步:创建服务注册构建器对象,通过配置对象中加载所有的配置信息 StandardServiceRegistryBuilder regbulider = new StandardServiceRegistryBuilder() .applySettings(config.getProperties()); // 创建注册服务 ServiceRegistry sry = regbulider.build(); // 第三步:创建会话工厂 sessionFactory = config.buildSessionFactory(sry); } public static void createTables(){ Configuration config = new Configuration().configure(); new SchemaExport(config).create(false, true); } /** * @return 获取当前会话对象 */ public static Session getSession() { return getSessionFactory().getCurrentSession(); } public static void sfClose() { getSessionFactory().close(); } public static void sessionClear() { getSession().clear();; } }
接下来设计基于泛型DAO的接口
包括常用 的CRUD操作和分页功能。
package com.feytuo.education.persistence; import java.util.List; /** * * 用hibernate框架HQL检索 * * 对数据库中表各个表的增删查改CRUD操作接口 * * @author YangKang * * @param <T> * 泛型 ,实体类 * @param <PK> * 泛型,实体类的主键类型 * * @date 2014/04/25 * * @version 1.0 * * @revise 2014/04/30 V1.1 * */ public interface IBaseDAO<T, PK> { /** * 保存指定实体 * * @param entity * 实体对象 */ public void save(T entity); /** * 更新指定实体 * * @param entity * 实体对象 */ public void update(T entity); /** * 删除指定实体 * * @param entity * 实体对象 * */ public void delete(T entity); public void saveOrUpdate(T entity); /** * 删除实体 * * @param entityClass * 实体类名 * @param id * 实体的id */ public void deteleById(Class<T> entityClass, PK id); /** * 更新实体 可用于添加 ,修改,删除操作 * * @param hql * 执行的的hql语句 * @param params * 参数,可有对象或多个对象,代替Hql中的"?"号 */ public void execute(final String hql, final Object[] params); /** * 获取所有实体集合 * * @param entityClass * 实体类名 * @return 结果集合 */ public List<T> query(Class<T> entityClass); /** * 按HQL条件查询列表 * * @param entityClass * 实体类名 * @param id * 实体id * @return 实体对象 */ public T findById(Class<T> entityClass, PK id); /** * 按具体属性内容查询 * * @param entityClass * @param propertyName * @param value * @return */ public T findByProperty(Class<T> entityClass, String propertyName, Object value); /** * 按hql条件查询列表 * * @param hql * 查询语句 支持连接查询和多条件查询 * @param params * @return */ public List<T> findByHql(String hql, Object[] params); /** * 查询指定sql语句的分页数据集合 * * @param entityClass * @param start * @param limit * @return */ public List<T> findByPage(Class<T> entityClass, int start, int limit); /** * 查询指定sql语句的分页数据集合 * * @param hql * @param params * @param start * @param limit * @return */ public List<T> findByPage(String hql, Object[] params, int start, int limit); }
DAO类的实现。
package com.feytuo.education.persistence; import java.io.Serializable; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; /** * Hibernate 框架<br /> * * 实体类的增删查改实现类 * * @author YangKang * * @param <T> * 实体类名 * @param <PK> * 实体类的主键类型 * * @date 2014/04/30 * * @version 1.0 * * @revise 2014/05/02 V1.1 */ public class BaseDAO<T, PK extends Serializable> implements IBaseDAO<T, PK> { /** * 添加实体 */ @Override public void save(T entity) { Session session = HibernateUtil.getSession(); session.beginTransaction(); session.save(entity); session.getTransaction().commit(); } /** * 更新实体 */ @Override public void update(T entity) { Session session = HibernateUtil.getSession(); session.beginTransaction(); session.update(entity); session.getTransaction().commit(); } /** * 更新实体 */ @Override public void saveOrUpdate(T entity) { Session session = HibernateUtil.getSession(); session.beginTransaction(); session.saveOrUpdate(entity); session.getTransaction().commit(); } /** * 删除实体 */ @Override public void delete(T entity) { Session session = HibernateUtil.getSession(); session.beginTransaction(); session.delete(entity); session.getTransaction().commit(); } /** * 按id删除实体 */ @Override public void deteleById(Class<T> entityClass, PK id) { Session session = HibernateUtil.getSession(); session.beginTransaction(); session.delete(findById(entityClass, id)); session.getTransaction().commit(); } /** * 执行自定义的sql语句,实现其中的添加,更新,删除的方法 */ @Override public void execute(String hql, Object[] params) { Session session = HibernateUtil.getSession(); session.beginTransaction(); Query query = session.createQuery(hql); if (null != params && params.length > 0) { for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } } // 执行hql语句 query.executeUpdate(); session.getTransaction().commit(); } /** * 获取所有实体 */ @SuppressWarnings("unchecked") @Override public List<T> query(Class<T> entityClass) { Session session = HibernateUtil.getSession(); session.beginTransaction(); String hql = "from " + entityClass.getName(); Query query = session.createQuery(hql); List<T> list = query.list(); session.getTransaction().commit(); return list; } @SuppressWarnings("unchecked") @Override public T findByProperty(Class<T> entityClass, String propertyName, Object value) { String hql = "from " + entityClass.getName() + " as model where model." + propertyName + "=?"; Session session = HibernateUtil.getSession(); session.beginTransaction(); Query query = session.createQuery(hql); query.setParameter(0, value); List<T> list = query.list(); session.getTransaction().commit(); if (null != list) { return list.get(0); } else { return null; } } /** * 按实体名和id获取实体 * * @param entityClass * @param id * @return */ @SuppressWarnings("unchecked") @Override public T findById(Class<T> entityClass, PK id) { Session session = HibernateUtil.getSession(); session.beginTransaction(); T entity = (T) session.get(entityClass, id); session.getTransaction().commit(); return entity; } /** * 按自定义的hql取得结果集 */ @Override @SuppressWarnings("unchecked") public List<T> findByHql(String hql, Object[] params) { Session session = HibernateUtil.getSession(); session.beginTransaction(); Query query = session.createQuery(hql); if (null != params && params.length > 0) { for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } } List<T> list = query.list(); session.getTransaction().commit(); return list; } /** * 分页使用 * * @param entityClass * @param start * @param limit * @return */ @SuppressWarnings("unchecked") @Override public List<T> findByPage(String hql, Object[] params, int start, int limit) { Session session = HibernateUtil.getSession(); session.beginTransaction(); List<T> list = null; try { Query query = session.createQuery(hql); if (params != null && params.length != 0) { for (int i = 0; i < params.length; i++) { query.setParameter(i, params[i]); } } if (limit != 0) { query.setFirstResult(start).setMaxResults(limit); } list = query.list(); session.getTransaction().commit(); } catch (Exception ef) { ef.printStackTrace(); session.getTransaction().rollback(); } return list; } /** * 分页使用 * * @param entityClass * @param start * @param limit * @return */ @SuppressWarnings("unchecked") @Override public List<T> findByPage(Class<T> entityClass, int start, int limit) { Session session = HibernateUtil.getSession(); String hql = "select from o " + entityClass.getName() + " o"; session.beginTransaction(); Query query = session.createQuery(hql); query.setFirstResult(start).setMaxResults(limit); List<T> list = query.list(); session.getTransaction().commit(); return list; } }
我在HibernateUtil 获取Session的方法是getCurrentSession(),所以在DAO实现类里是无需close session的,若使用的是openSession(),则实现类必须要close session。至于为什么要close,这和文件一样,你懂得。
在此Hibernate 基于泛型DAO类设计完成,如还有其他的需求,可在接口中扩展。