接口设计:
package org.forever.dao; import java.util.List; import org.forever.pagination.PageInfo; /** * 通用dao接口 * @author 陈均 * */ public interface IGeneralDao { /** * 创建实体到数据库 * @param entity * @throws Exception */ public void create(Object entity)throws Exception; /** * 根据条件删除实体信息(排除in条件的操作)<br/> * 例子:<br/> * List<Condition> conditions = Arrays.asList( new Condition("id",new Long(2) ,Operation.EQ) );<br/> User user = new User();<br/> user.setConditions(conditions);<br/> 删除单个实体:<br/> User user = new User(new Long(22));<br/> generalDao.delete(user);<br/> */ public int delete(PageInfo entity)throws Exception; /** * 删除单个实体信息 * 批量删除实体信息,该方法只适用于in操作的<br/> * 考虑性能的原因,所以单独写的一个方法,实现是基于sql实现的,<br/> * 没有单独解析sql字段,实体字段必须和数据库字段名字一样<br/> * 例子:<br/> * 批量删除:<br/> * List<Long> ids = new ArrayList<Long>();<br/> for (int i = 47000; i < 147000; i++) {<br/> ids.add(new Long(i));<br/> }<br/> List<Condition> conditions = Arrays.asList(new Condition("id", ids,<br/> Operation.IN));<br/> User user = new User();<br/> user.setConditions(conditions);<br/> int count = generalDao.batchDelete(user);<br/> 删除单个实体:<br/> User user = new User(new Long(22));<br/> generalDao.batchDelete(user);<br/> */ public int batchDelete(PageInfo entity)throws Exception; /** * 批量或者单个更新实体信息(排除in条件的操作)<br/> * 例子:<br/> * 对单个实体更新(可对版本进行控制):<br/> * User user = new User(new Long(94));<br/> user = (User) generalDao.query(user).get(0);<br/> Random random = new Random();<br/> user.setCname("陈均"+random.nextInt());<br/> generalDao.update(user);<br/> 批量更新(不能控制版本):<br/> List<Condition> conditions = Arrays.asList(new Condition("id",<br/> new Object[] { new Long(147000), new Long(157000) },<br/> Operation.BETWEEN));<br/> User user = new User();<br/> user.setCname("陈均");<br/> user.setConditions(conditions);<br/> int count = generalDao.update(user);<br/> * */ public int update(PageInfo entity)throws Exception; /** * 批量更新实体信息,适用于in操作的<br/> * 考虑性能的原因,所以单独写的一个方法,实现是基于sql实现的<br/> * * 没有单独解析sql字段,实体字段必须和数据库字段名字一样<br/> * 这种批量更新不考虑版本控制<br/> * 例子:<br/> * List<Long> ids = new ArrayList<Long>();<br/> for (int i = 147000; i < 157000; i++) {<br/> ids.add(new Long(i));<br/> }<br/> List<Condition> conditions = Arrays.asList(new Condition("id", ids,<br/> Operation.IN));<br/> User user = new User();<br/> user.setCname("陈均来了");<br/> user.setConditions(conditions);<br/> int count = generalDao.batchUpdate(user);<br/> */ public int batchUpdate(PageInfo entity)throws Exception; /** * 根据id查询单个对象<br/> * User user = new User(new Long(95));<br/> * user = (User) generalDao.query(user).get(0);<br/> * */ public Object queryEntity(PageInfo entity)throws Exception; /** * * 根据任意条件查询多条信息<br/> * SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");<br/> Date startTime = dateFormat.parse("2010-02-01");<br/> Date endTime = dateFormat.parse("2010-03-02");<br/> List<Condition> conditions = Arrays.asList(<br/> new Condition("stuGrade","一年级", Operation.EQ),<br/> new Condition("stuAge", 12, Operation.GE),<br/> new Condition("stuAge", 19, Operation.LE), <br/> new Condition("stuClass","二班", Operation.EQ),<br/> new Condition("stuName", "%stor%",Operation.LIKE), <br/> new Condition("stuSex", Arrays.asList("男", "女"), Operation.IN),<br/> new Condition("stuTime", new Object[] { startTime, endTime },Operation.BETWEEN),<br/> new Condition("stuAge",new Object[] { 14, 18 }, Operation.BETWEEN));<br/> List<Order> orders = Arrays.asList(<br/> new Order("stuName", OrderType.DESC), <br/> new Order("stuAge",OrderType.DESC));<br/> Student student = new Student();<br/> student.setConditions(conditions);<br/> student.setOrders(orders);<br/> List<?> list = generalDao.query(student);<br/> */ public List<?> queryList(PageInfo entity)throws Exception; /** * 外置命名查询 */ public Object query(String queryName,Object... params)throws Exception; }
hibernate实现设计:
package org.forever.sales.dao.hibernateImpl; import java.lang.reflect.Field; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.forever.dao.IGeneralDao; import org.forever.pagination.Condition; import org.forever.pagination.Operation; import org.forever.pagination.Order; import org.forever.pagination.OrderType; import org.forever.pagination.PageInfo; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.stereotype.Repository; @Repository("generalDao") public class GeneralDaoImpl implements IGeneralDao { private static final String SET = "SET"; private static final String UPDATE = "UPDATE"; private static final String EMPTY_STRING = ""; private static final String CONDITION_SQL = "#condition_sql#"; private static final String DELETE = "DELETE"; private static final String RIGTH_BRACKETS = ")"; private static final String LEFT_BRACKETS = "("; private static final String _1_1 = "1=1"; private static final String WHERE = "WHERE"; private static final String FROM = "FROM"; private static final String SPACE = " "; private static final String MODE = "mode"; private static Log log = LogFactory.getLog(GeneralDaoImpl.class); public static final String ENTITY_NAME = "#entityName#"; public static final String CONDITION_HQL = "#condition_hql#"; public static final String FIELDS = "#fields#"; public static final String TABLE_NAME = "#tableName#"; public static final String ORDER_HQL = "#order_hql#"; public static final String SELECT = "SELECT"; public static final String COUNT = "COUNT"; private String hqlCountTemplate; private String hqlTemplate; private String deleteTemplate; private String updateTemplate; private static Map<String,String> tabMapCache = new HashMap<String, String>(); public GeneralDaoImpl() { // hqlCountTemplate = // "SELECT COUNT(mode) FROM #entityName# mode WHERE 1=1 #condition_hql#"; StringBuffer sb = new StringBuffer(); sb.append(SELECT).append(SPACE).append(COUNT).append(LEFT_BRACKETS) .append(MODE).append(RIGTH_BRACKETS).append(SPACE).append(FROM) .append(SPACE).append(ENTITY_NAME).append(SPACE).append(MODE) .append(SPACE).append(WHERE).append(SPACE).append(_1_1).append( SPACE).append(CONDITION_HQL); hqlCountTemplate = sb.toString(); sb = new StringBuffer(); sb.append(SELECT).append(SPACE).append(MODE).append(SPACE).append(FROM) .append(SPACE).append(ENTITY_NAME).append(SPACE).append(MODE) .append(SPACE).append(WHERE).append(SPACE).append(_1_1).append( SPACE).append(CONDITION_HQL); // hqlTemplate = // "SELECT mode FROM #entityName# mode WHERE 1=1 #condition_hql# #order_hql#"; hqlTemplate = sb.toString(); sb = new StringBuffer(); sb.append(DELETE).append(SPACE).append(FROM).append(SPACE).append( TABLE_NAME).append(SPACE).append(WHERE).append(SPACE).append( _1_1).append(SPACE).append(CONDITION_SQL); // deleteTemplate = "DELETE FROM #tableName# WHERE 1=1 #condition_sql#"; deleteTemplate = sb.toString(); // updateTemplate = // "UPDATE #entityName# mode SET #fields# WHERE 1=1 #condition_hql# "; sb = new StringBuffer(); sb.append(UPDATE).append(SPACE).append(ENTITY_NAME).append(SPACE) .append(MODE).append(SPACE).append(SET).append(SPACE).append( FIELDS).append(SPACE).append(WHERE).append(SPACE) .append(_1_1).append(SPACE).append(CONDITION_HQL); updateTemplate = sb.toString(); } @Resource private HibernateTemplate hibernateTemplate; public void create(Object entity) throws Exception { log.info("create " + entity.getClass()); hibernateTemplate.persist(entity); } public int delete(final PageInfo entity) throws Exception { return hibernateTemplate.execute(new HibernateCallback<Integer>() { public Integer doInHibernate(Session session) throws HibernateException, SQLException { String deleteTemplate = "DELETE #entityName# mode WHERE 1=1 #condition_hql#"; List<Object> values = new ArrayList<Object>(); String condition_hql = preConditionHQL(entity, values); if (EMPTY_STRING.equals(condition_hql)) { session.delete(entity); return 1; } String delete = deleteTemplate.replaceAll(CONDITION_HQL, condition_hql).replaceAll(ENTITY_NAME, entity.getClass().getSimpleName()); Query query = session.createQuery(delete); setQueryParameter(query, values); return query.executeUpdate(); } }); } // 面向单个对象的分页写法,对于连表分页不适用 public List<?> query(final PageInfo entity) throws Exception { return hibernateTemplate.executeFind(new HibernateCallback<List<?>>() { public List<?> doInHibernate(Session session) throws HibernateException, SQLException { return executeHQL(entity, session); // return executeQBC(entity, session); } }); } public int update(final PageInfo entity) throws Exception { return hibernateTemplate.execute(new HibernateCallback<Integer>() { public Integer doInHibernate(Session session) throws HibernateException, SQLException { List<Object> values = new ArrayList<Object>(); String fields = preField(entity, values); String condition_hql = preConditionHQL(entity, values); if (EMPTY_STRING.equals(condition_hql)) { hibernateTemplate.merge(entity); return 1; } String update = updateTemplate.replaceAll(CONDITION_HQL, condition_hql).replaceAll(FIELDS, fields).replaceAll( ENTITY_NAME, entity.getClass().getSimpleName()); System.out.println("update = " + update); Query query = session.createQuery(update); setQueryParameter(query, values); return query.executeUpdate(); } }); } public String getTableName(Object entity){ String className = entity.getClass().getName(); SAXReader reader = new SAXReader(); String tableName = tabMapCache.get(className); if(tableName == null){ String entityConfiXml = className.replaceAll("\\.", "/")+".hbm.xml"; Document doc; try { doc = reader.read(GeneralDaoImpl.class.getClassLoader().getResourceAsStream(entityConfiXml)); List<?> list = doc.selectNodes("/hibernate-mapping/class[@name='"+className+"']"); if(list.size()==1){ Element element = (Element) list.get(0); tableName = element.attributeValue("table"); tabMapCache.put(className, tableName); }else{ throw new RuntimeException("没有找到类" + className + "对应的配置文件xml"); } } catch (DocumentException e) { throw new RuntimeException(e); } } return tableName; } public int batchDelete(final PageInfo entity) throws Exception { return hibernateTemplate.execute(new HibernateCallback<Integer>() { public Integer doInHibernate(Session session) throws HibernateException, SQLException { String tableName = getTableName(entity); List<Object> values = new ArrayList<Object>(); String condition_sql = preConditionSQL(entity, values); if (EMPTY_STRING.equals(condition_sql)) { session.delete(entity); return 1; } String delete = deleteTemplate.replaceAll(CONDITION_SQL, condition_sql).replaceAll(TABLE_NAME, tableName); log.info("delete = " + delete); Query query = session.createSQLQuery(delete); setQueryParameter(query, values); return query.executeUpdate(); } }); } public int batchUpdate(final PageInfo entity) throws Exception { return hibernateTemplate.execute(new HibernateCallback<Integer>() { public Integer doInHibernate(Session session) throws HibernateException, SQLException { String updateTemplate = new String( "UPDATE #tableName# SET #fields# WHERE 1=1 #condition_sql#"); List<Object> values = new ArrayList<Object>(); String tableName = getTableName(entity); String fields = preField(entity, values); String condition_sql = preConditionSQL(entity, values); if (EMPTY_STRING.equals(condition_sql)) { hibernateTemplate.update(entity); return 1; } String update = updateTemplate.replaceAll(CONDITION_HQL, condition_sql).replaceAll(FIELDS, fields).replaceAll( TABLE_NAME, tableName); System.out.println("update = " + update); Query query = session.createSQLQuery(update); setQueryParameter(query, values); return query.executeUpdate(); } }); } /** * 处理字段语句hql,用于更新用 */ public String preField(PageInfo entity, List<Object> values) { StringBuffer fields = new StringBuffer(); Class<?> c = entity.getClass(); for (Field field : c.getDeclaredFields()) { String fieldName = field.getName(); try { field.setAccessible(true); Object value = field.get(entity); if (value != null) { fields.append(fieldName + "=?,"); values.add(value); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } if (fields.length() > 0) { fields.replace(fields.length() - 1, fields.length(), EMPTY_STRING); } return fields.toString(); } /** * 处理排序解析hql */ public String preOrder(PageInfo entity) { StringBuffer c = new StringBuffer(); List<Order> orders = entity.getOrders(); if (orders.size() > 0) { c.append(" ORDER BY "); } for (Order order : orders) { String propertyName = order.getPropertyName(); OrderType orderType = order.getOrderType(); c.append("mode." + propertyName + orderType + ","); } if (orders.size() > 0) { c.replace(c.length() - 1, c.length(), EMPTY_STRING); } return c.toString(); } /** * 条件解析SQL该方法作用于批量更新和批量删除使用 */ public String preConditionSQL(PageInfo entity, List<Object> param) { StringBuffer c = new StringBuffer(); for (Condition condition : entity.getConditions()) { String propertyName = condition.getPropertyName(); Object value = condition.getPropertyValue(); Operation operation = condition.getOperation(); switch (operation) { case LIKE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case BETWEEN: Object[] params = (Object[]) value; c.append(" AND " + propertyName + operation + "? AND ?"); param.add(params[0]); param.add(params[1]); break; case IN: Collection<?> values = (Collection<?>) value; c.append(" AND " + propertyName + operation + LEFT_BRACKETS); for (Object object : values) { c.append("?,"); param.add(object); } c.replace(c.length() - 1, c.length(), EMPTY_STRING); c.append(RIGTH_BRACKETS); break; case EQ: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case GE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case GT: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case LE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case LT: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case NE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; } } return c.toString(); } /** * 条件解析hql */ public String preConditionHQL(PageInfo entity, List<Object> param) { StringBuffer c = new StringBuffer(); for (Condition condition : entity.getConditions()) { String propertyName = condition.getPropertyName(); Object value = condition.getPropertyValue(); Operation operation = condition.getOperation(); switch (operation) { case LIKE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case BETWEEN: Object[] params = (Object[]) value; c.append(" AND " + propertyName + operation + "? AND ?"); param.add(params[0]); param.add(params[1]); break; case IN: c.append(" AND " + propertyName + operation + LEFT_BRACKETS); Class<?> clazz = value.getClass(); if (clazz.isArray()) { for (Object object : (Object[]) value) { c.append("?,"); param.add(object); } } else if (value instanceof Collection<?>) { for (Object object : (Collection<?>) value) { c.append("?,"); param.add(object); } } c.replace(c.length() - 1, c.length(), EMPTY_STRING); c.append(RIGTH_BRACKETS); break; case EQ: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case GE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case GT: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case LE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case LT: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; case NE: c.append(" AND " + propertyName + operation + "?"); param.add(value); break; } } return c.toString(); } public List<?> executeHQL(PageInfo entity, Session session) { List<Object> values = new ArrayList<Object>(); String condition_hql = preConditionHQL(entity, values); String order_hql = preOrder(entity); String hqlCount = hqlCountTemplate.replaceAll(CONDITION_HQL, condition_hql).replaceAll(ENTITY_NAME, entity.getClass().getSimpleName()); String hql = hqlTemplate.replaceAll(CONDITION_HQL, condition_hql) .replaceAll(ORDER_HQL, order_hql).replaceAll(ENTITY_NAME, entity.getClass().getSimpleName()); log.info("hqlCount=" + hqlCount); log.info("hql=" + hql); Query query = session.createQuery(hqlCount); setQueryParameter(query, values); Object uqResult = query.uniqueResult(); entity.setTotalItems(Integer.parseInt(uqResult.toString())); setTotalPage(entity); query = session.createQuery(hql); setQueryParameter(query, values); return query.setFirstResult( (entity.getCurrentPage() - 1) * entity.getPageSize()) .setMaxResults(entity.getPageSize()).list(); } /** * 设置分页语句参数值 */ public void setQueryParameter(Query query, List<Object> values) { for (int i = 0; i < values.size(); i++) { query.setParameter(i, values.get(i)); } } /** * QBC形式的解析 */ public Object executeQBC(PageInfo entity, Session session) { Criteria qbc = session.createCriteria(entity.getClass()); qbc.setProjection(Projections.rowCount()); preCondition(qbc, entity.getConditions()); Object uqResult = qbc.uniqueResult(); entity.setTotalItems(Integer.parseInt(uqResult.toString())); setTotalPage(entity); qbc.setProjection(null); preOrder(qbc, entity.getOrders()); return qbc.setFirstResult( (entity.getCurrentPage() - 1) * entity.getPageSize()) .setMaxResults(entity.getPageSize()).list(); } /** * 设置总页数 * */ public void setTotalPage(PageInfo pageInfo) { pageInfo .setTotalPage(pageInfo.getTotalItems() % pageInfo.getPageSize() == 0 ? pageInfo .getTotalItems() / pageInfo.getPageSize() : pageInfo.getTotalItems() / pageInfo.getPageSize() + 1); } /** * 处理排序qbc */ public void preOrder(Criteria qbc, List<Order> orders) { for (Order order : orders) { String propertyName = order.getPropertyName(); switch (order.getOrderType()) { case ASC: qbc.addOrder(org.hibernate.criterion.Order.asc(propertyName)); break; case DESC: qbc.addOrder(org.hibernate.criterion.Order.desc(propertyName)); break; } } } /** * 处理条件qbc */ public void preCondition(Criteria qbc, List<Condition> conditions) { for (Condition condition : conditions) { String propertyName = condition.getPropertyName(); Object value = condition.getPropertyValue(); switch (condition.getOperation()) { case LIKE: qbc.add(Restrictions.like(propertyName, value.toString(), MatchMode.ANYWHERE)); break; case BETWEEN: Object[] params = (Object[]) value; qbc.add(Restrictions .between(propertyName, params[0], params[1])); break; case IN: Collection<?> values = (Collection<?>) value; qbc.add(Restrictions.in(propertyName, values)); break; case EQ: qbc.add(Restrictions.eq(propertyName, value)); break; case GE: qbc.add(Restrictions.ge(propertyName, value)); break; case GT: qbc.add(Restrictions.gt(propertyName, value)); break; case LE: qbc.add(Restrictions.le(propertyName, value)); break; case LT: qbc.add(Restrictions.lt(propertyName, value)); break; case NE: qbc.add(Restrictions.ne(propertyName, value)); break; } } } public Object query(String queryName, Object... values) throws Exception { return hibernateTemplate.findByNamedQuery(queryName, values); } @Override public Object queryEntity(PageInfo entity) throws Exception { try { Class<?> c = entity.getClass(); Field field = c.getDeclaredField("id"); field.setAccessible(true); Integer id = Integer.parseInt(field.get(entity).toString()); return hibernateTemplate.get(c, id); } catch (Exception e) { e.printStackTrace(); return null; } } @Override public List<?> queryList(final PageInfo entity) throws Exception { return hibernateTemplate.executeFind(new HibernateCallback<List<?>>() { public List<?> doInHibernate(Session session) throws HibernateException, SQLException { return executeHQL(entity, session); } }); } }