接口设计:
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);
}
});
}
}