Hibernate与spring整合总结AbstractHibernateDAOImpl
? 本人学习了一个新项目,总结了一下。有很多不足的地方,希望高手指点:
首先,在dao包下新建abstractDAO.java文件,如下:
??package com.huangt.dao;
import java.util.Collection;import java.util.Iterator;import java.util.List;import org.hibernate.Criteria;import org.hibernate.LockMode;import org.hibernate.criterion.DetachedCriteria;@SuppressWarnings("unchecked")public interface AbstractDAO<T, PK> {// 根据主键获取实体。如果没有相应的实体,返回 null。public T get(PK id);// 根据主键获取实体并加锁。如果没有相应的实体,返回 null。public T getWithLock(PK id, LockMode lock);// 根据主键获取实体。如果没有相应的实体,抛出异常。public T load(PK id);// 根据主键获取实体并加锁。如果没有相应的实体,抛出异常。public T loadWithLock(PK id, LockMode lock);// 获取全部实体。public List<T> loadAll();// 更新实体public void update(T entity) throws Exception;// 更新实体并加锁public void updateWithLock(T entity, LockMode lock);// 存储实体到数据库public void save(T entity) throws Exception;// 增加或更新实体public void saveOrUpdate(T entity);// 增加或更新集合中的全部实体public void saveOrUpdateAll(Collection<T> entities);// 删除指定的实体public void delete(T entity);// 加锁并删除指定的实体public void deleteWithLock(T entity, LockMode lock);// 根据主键删除指定实体public void deleteByKey(PK id);// 根据主键加锁并删除指定的实体public void deleteByKeyWithLock(PK id, LockMode lock);// 删除集合中的全部实体public void deleteAll(Collection<T> entities);// 使用HSQL语句直接增加、更新、删除实体public int bulkUpdate(String queryString);// 使用带参数的HSQL语句增加、更新、删除实体public int bulkUpdate(String queryString, Object[] values);// 使用HSQL语句检索数据public List find(String queryString);// 使用带参数的HSQL语句检索数据public List<T> find(String queryString, Object[] values) throws Exception;// 使用带命名的参数的HSQL语句检索数据public List findByNamedParam(String queryString, String[] paramNames,Object[] values);// 使用命名的HSQL语句检索数据public List findByNamedQuery(String queryName);// 使用带参数的命名HSQL语句检索数据public List findByNamedQuery(String queryName, Object[] values);// 使用带命名参数的命名HSQL语句检索数据public List findByNamedQueryAndNamedParam(String queryName,String[] paramNames, Object[] values);// 使用HSQL语句检索数据,返回 Iteratorpublic Iterator iterate(String queryString);// 使用带参数HSQL语句检索数据,返回 Iteratorpublic Iterator iterate(String queryString, Object[] values);// 关闭检索返回的 Iteratorpublic void closeIterator(Iterator it);// 创建与会话无关的检索标准public DetachedCriteria createDetachedCriteria();// 创建与会话绑定的检索标准public Criteria createCriteria();// 检索满足标准的数据public List findByCriteria(DetachedCriteria criteria);// 检索满足标准的数据,返回指定范围的记录public List findByCriteria(DetachedCriteria criteria, int firstResult,int maxResults);// 使用指定的实体及属性检索(满足除主键外属性=实体值)数据public List<T> findEqualByEntity(T entity, String[] propertyNames);// 使用指定的实体及属性检索(满足属性 like 串实体值)数据public List<T> findLikeByEntity(T entity, String[] propertyNames);// 使用指定的检索标准获取满足标准的记录数public Integer getRowCount(DetachedCriteria criteria);// 使用指定的检索标准检索数据,返回指定统计值(max,min,avg,sum)public Object getStatValue(DetachedCriteria criteria, String propertyName,String StatName);// 加锁指定的实体public void lock(T entity, LockMode lock);// 强制初始化指定的实体public void initialize(Object proxy);// 强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)public void flush();/************以下为分页代码可根据个人需求而定***************/ public List queryForPage(final String hql, final int offset,final int length);public int getAllRowCount(String hql) throws Exception;}?
? ? 接着实现该类接口,在包dao.impl下,AbstractHibernateDAOImpl.java。如下:
? ??package com.huangt.dao.impl;
import java.io.Serializable;import java.sql.SQLException;import java.util.Collection;import java.util.Iterator;import java.util.List;import org.apache.log4j.Logger;import org.hibernate.Criteria;import org.hibernate.HibernateException;import org.hibernate.LockMode;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.criterion.DetachedCriteria;import org.hibernate.criterion.Example;import org.hibernate.criterion.MatchMode;import org.hibernate.criterion.Order;import org.hibernate.criterion.Projections;import org.hibernate.criterion.Restrictions;import org.springframework.orm.hibernate3.HibernateCallback;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import com.sun.org.apache.commons.beanutils.PropertyUtils;import com.zjsoft.dao.AbstractDAO;@SuppressWarnings("unchecked")public abstract class AbstractHibernateDAOImpl<T extends Serializable, PK extends Serializable>extends HibernateDaoSupport implements AbstractDAO <T, PK>{protected final Logger log = Logger.getLogger(getClass()); protected Class<T> domainClass = getDomainClass();/** * Method to return the class of the domain object */protected abstract Class<T> getDomainClass(); // -------------------- 基本检索、增加、修改、删除操作 -------------------- // 根据主键获取实体。如果没有相应的实体,返回 null。 public T get(PK id) { log.info("操作实体:" + domainClass.getName()); return (T) getHibernateTemplate().get(domainClass.getName(),id); } // 根据主键获取实体并加锁。如果没有相应的实体,返回 null。 public T getWithLock(PK id, LockMode lock) { T t = (T) getHibernateTemplate().get(domainClass.getName(), id, lock); if (t != null) { this.flush(); // 立即刷新,否则锁不会生效。 } return t; } // 根据主键获取实体。如果没有相应的实体,抛出异常。 public T load(PK id) { return (T) getHibernateTemplate().load(domainClass.getName(), id); } // 根据主键获取实体并加锁。如果没有相应的实体,抛出异常。 public T loadWithLock(PK id, LockMode lock) { T t = (T) getHibernateTemplate().load(domainClass.getName(), id, lock); if (t != null) { this.flush(); // 立即刷新,否则锁不会生效。 } return t; } // 获取全部实体。 public List<T> loadAll() { return (List<T>) getHibernateTemplate().loadAll(domainClass); } // loadAllWithLock() ? // 更新实体 public void update(T entity) throws Exception { log.info("操作实体:" + entity); getHibernateTemplate().update(entity); } // 更新实体并加锁 public void updateWithLock(T entity, LockMode lock) { getHibernateTemplate().update(entity, lock); this.flush(); // 立即刷新,否则锁不会生效。 } // 存储实体到数据库 public void save(T entity) throws Exception { getHibernateTemplate().save(entity); } // saveWithLock()? // 增加或更新实体 public void saveOrUpdate(T entity) { getHibernateTemplate().saveOrUpdate(entity); } // 增加或更新集合中的全部实体 public void saveOrUpdateAll(Collection<T> entities) { getHibernateTemplate().saveOrUpdateAll(entities); } // 删除指定的实体 public void delete(T entity) { getHibernateTemplate().delete(entity); } // 加锁并删除指定的实体 public void deleteWithLock(T entity, LockMode lock) { getHibernateTemplate().delete(entity, lock); this.flush(); // 立即刷新,否则锁不会生效。 } // 根据主键删除指定实体 public void deleteByKey(PK id) { this.delete(this.load(id)); } // 根据主键加锁并删除指定的实体 public void deleteByKeyWithLock(PK id, LockMode lock) { this.deleteWithLock(this.load(id), lock); } // 删除集合中的全部实体 public void deleteAll(Collection<T> entities) { getHibernateTemplate().deleteAll(entities); } // -------------------- HSQL ---------------------------------------------- // 使用HSQL语句直接增加、更新、删除实体 public int bulkUpdate(String queryString) { return getHibernateTemplate().bulkUpdate(queryString); } // 使用带参数的HSQL语句增加、更新、删除实体 public int bulkUpdate(String queryString, Object[] values) { return getHibernateTemplate().bulkUpdate(queryString, values); } // 使用HSQL语句检索数据 public List find(String queryString) { return getHibernateTemplate().find(queryString); } // 使用带参数的HSQL语句检索数据 public List<T> find(String queryString, Object[] values) { return getHibernateTemplate().find(queryString, values); } // 使用带命名的参数的HSQL语句检索数据 public List findByNamedParam(String queryString, String[] paramNames, Object[] values) { return getHibernateTemplate().findByNamedParam(queryString, paramNames, values); } // 使用命名的HSQL语句检索数据 public List findByNamedQuery(String queryName) { return getHibernateTemplate().findByNamedQuery(queryName); } // 使用带参数的命名HSQL语句检索数据 public List findByNamedQuery(String queryName, Object[] values) { return getHibernateTemplate().findByNamedQuery(queryName, values); } // 使用带命名参数的命名HSQL语句检索数据 public List findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values) { return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramNames, values); } // 使用HSQL语句检索数据,返回 Iterator public Iterator iterate(String queryString) { return getHibernateTemplate().iterate(queryString); } // 使用带参数HSQL语句检索数据,返回 Iterator public Iterator iterate(String queryString, Object[] values) { return getHibernateTemplate().iterate(queryString, values); } // 关闭检索返回的 Iterator public void closeIterator(Iterator it) { getHibernateTemplate().closeIterator(it); } // -------------------------------- Criteria ------------------------------ // 创建与会话无关的检索标准 public DetachedCriteria createDetachedCriteria() { return DetachedCriteria.forClass(domainClass); } // 创建与会话绑定的检索标准 public Criteria createCriteria() { return this.createDetachedCriteria().getExecutableCriteria(this.getSession()); } // 检索满足标准的数据 public List findByCriteria(DetachedCriteria criteria) { return getHibernateTemplate().findByCriteria(criteria); } // 检索满足标准的数据,返回指定范围的记录 public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) { return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults); } // 使用指定的实体及属性检索(满足除主键外属性=实体值)数据 public List<T> findEqualByEntity(T entity, String [] propertyNames) { Criteria criteria = this.createCriteria(); Example exam = Example.create(entity); exam.excludeZeroes(); String [] defPropertys = getSessionFactory().getClassMetadata(domainClass.getName()).getPropertyNames(); for(String defProperty : defPropertys) { int ii = 0; for(ii = 0; ii < propertyNames.length; ++ii) { if(defProperty.equals(propertyNames[ii])) { criteria.addOrder(Order.asc(defProperty)); break; } } if(ii == propertyNames.length) { exam.excludeProperty(defProperty); } } criteria.add(exam); return (List<T>) criteria.list(); } // 使用指定的实体及属性检索(满足属性 like 串实体值)数据 public List<T> findLikeByEntity(T entity, String [] propertyNames) { Criteria criteria = this.createCriteria(); for(String property : propertyNames) { try { Object value = PropertyUtils.getProperty(entity, property); if(value instanceof String) { criteria.add(Restrictions.like(property, (String) value, MatchMode.ANYWHERE)); criteria.addOrder(Order.asc(property)); } else { criteria.add(Restrictions.eq(property, value)); criteria.addOrder(Order.asc(property)); } } catch(Exception ex) { // 忽略无效的检索参考数据。 } } return (List<T>) criteria.list(); } // 使用指定的检索标准获取满足标准的记录数 public Integer getRowCount(DetachedCriteria criteria) { criteria.setProjection(Projections.rowCount()); List list = this.findByCriteria(criteria, 0, 1); return (Integer) list.get(0); } // 使用指定的检索标准检索数据,返回指定统计值(max,min,avg,sum) public Object getStatValue(DetachedCriteria criteria, String propertyName, String StatName) { if (StatName.toLowerCase().equals("max")) criteria.setProjection(Projections.max(propertyName)); else if(StatName.toLowerCase().equals("min")) criteria.setProjection(Projections.min(propertyName)); else if(StatName.toLowerCase().equals("avg")) criteria.setProjection(Projections.avg(propertyName)); else if(StatName.toLowerCase().equals("sum")) criteria.setProjection(Projections.sum(propertyName)); else return null; List list = this.findByCriteria(criteria, 0, 1); return list.get(0); } // -------------------------------- Others -------------------------------- // 加锁指定的实体 public void lock(T entity, LockMode lock) { getHibernateTemplate().lock(entity, lock); } // 强制初始化指定的实体 public void initialize(Object proxy) { getHibernateTemplate().initialize(proxy); } // 强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新) public void flush() { getHibernateTemplate().flush(); } //=========================== 分页代码===========================================public List queryForPage(final String hql, final int offset,final int length) { List list = getHibernateTemplate().executeFind(new HibernateCallback() {public Object doInHibernate(Session session)throws HibernateException, SQLException {Query query = session.createQuery(hql);query.setFirstResult(offset);query.setMaxResults(length);List list = query.list();return list;}});return list;}public int getAllRowCount(String hql) throws Exception {return this.getHibernateTemplate().find(hql).size();} }?
好的,现在开始编写service。首先编写接口类,BaseService.java 如下:
?
package com.zjsoft.service;import java.io.Serializable;import java.util.List;import com.zjsoft.bean.Page;@SuppressWarnings("unchecked")public interface BaseService<T extends Serializable> {public void save(T t) throws Exception;public void saveAll(List objs) throws Exception;public void delete(T t);public void deleteAll(List objs);public void update(T t) throws Exception; public void updateAll(List objs) throws Exception;public void deleteById(Serializable id) throws Exception;public void deleteByIDS(Serializable[] ids) throws Exception;public T getByID(Serializable id) throws Exception;public Page listAll(int pageNum, int pageSize) throws Exception;public List<T> listAll() throws Exception;public Page queryPage(int pageSize, int page, String hql) throws Exception;public List listByIDs(Serializable[] ids) throws Exception;}?
?根据需求选择所要用到的方法,以上只是选择了一部分。
?接着实现该接口,BaseServiceImpl.java ,如下:
?package com.zjsoft.service.impl;
import java.io.Serializable;import java.util.ArrayList;import java.util.List;import com.zjsoft.bean.Page;import com.zjsoft.dao.AbstractDAO;import com.zjsoft.service.BaseService; @SuppressWarnings("unchecked") public abstract class BaseServiceImpl<T extends Serializable> implements BaseService<T>{ private AbstractDAO abstractDAO ; public AbstractDAO getAbstractDAO() {return abstractDAO;}public void setAbstractDAO(AbstractDAO abstractDAO) {this.abstractDAO = abstractDAO;}public abstract AbstractDAO getDAO(); public void save(T t) throws Exception {getDAO().save(t);}public void saveAll(List objs) throws Exception{getDAO().saveOrUpdateAll(objs);}public void delete(T t) {getDAO().delete(t);}public void update(T t) throws Exception {getDAO().update(t);}public void updateAll(List objs) throws Exception {for (int i = 0; i < objs.size(); i++) {this.getDAO().update(objs.get(i)) ;}}public void deleteById(Serializable id) throws Exception {Object obj = getDAO().load(id);getDAO().delete(obj);}public void deleteByIDS(Serializable[] ids) throws Exception{ for(int i = 0; i < ids.length; i ++){ getDAO().deleteByKey(ids[i]); } }public void deleteAll(List objs) {for (int i = 0; i < objs.size(); i++) { getDAO().delete(objs.get(i));}}public T getByID(Serializable id) throws Exception{return (T) getDAO().get(id);}public List<T> listAll() throws Exception{return getDAO().loadAll();}public Page queryPage(int pageSize, int page, String hql) throws Exception {int allRow = getDAO().getAllRowCount(hql);int totalPage = Page.countTotalPage(pageSize, allRow);final int offset = Page.countOffset(pageSize, page);final int length = pageSize;final int currentPage = Page.countCurrentPage(page);List<?> list = getDAO().queryForPage(hql, offset, length);//封装Page对象Page pageBean = new Page();pageBean.setPageSize(pageSize);pageBean.setCurrentPage(currentPage);pageBean.setAllRow(allRow);pageBean.setTotalPage(totalPage);pageBean.setList(list);pageBean.init();return pageBean;}/** * 根据id查询,返回list * list封装了对象 * */public List listByIDs(Serializable[] ids) throws Exception{List<T> sysList = new ArrayList<T>() ;for (int i = 0; i < ids.length; i++) {T t = (T) getDAO().get(ids[i]) ;sysList.add(t);}return sysList;}}?
??注意:此BaseServiceImpl.java.为抽象类,需要真正的业务逻辑类去继承。其中类中用到了getDAO()方法。直接返回 ? ? ? ?该DAO。
?
?
<!--EndFragment-->?以上的基础类已经写好了,下面开始真实的DAO跟service。
?下面的DAO接口就比较简单了,只需继承AbstractDAO接口就好了,对于DAO的实现类了要继承AbstractDAOImpl,还得实现自身的DAO。?SystemUserDAOImp.javal ?
如下:
?
package com.huangt.dao.impl;import com.huangt.bean.SystemUser;import com.huangtt.dao.SystemUserDAO;public class SystemUserDAOImpl extends AbstractHibernateDAOImpl<SystemUser, Integer> implements SystemUserDAO {@Override protected Class<SystemUser> getDomainClass() { return SystemUser.class; }}? 以上@Override?getDomainClass()的方法。以便service的调用。
?
? service接口也很简单,只需继承BaseService即可。对于该实现类SystemUserServiceImpl.java
? 如下:
?
package com.huangt.service.impl;import java.io.Serializable;import java.util.ArrayList;import java.util.List;import com.huangt.bean.SystemUser;import com.huangt.dao.AbstractDAO;import com.huangt.dao.SystemUserDAO;import com.huangt.service.SystemUserService;@SuppressWarnings("unchecked")public class SystemUserServiceImpl extends BaseServiceImpl implements SystemUserService {private SystemUserDAO systemuserDAO;public SystemUserDAO getSystemUserDAO() {return systemuserDAO;}public void setSystemUserDAO(SystemUserDAO systemUserDAO) {this.systemuserDAO = systemUserDAO;}@Overridepublic AbstractDAO getDAO() {return systemuserDAO;}//加载所有系统用户public List<SystemUser> loadAll() throws Exception {return this.getDAO().loadAll() ;}}?注意:以上需要Override?getDAO()方法,提供下面的loadAll()调用。
?
?
?
?
<!--EndFragment-->