import com.tp.util.DataGridModel;
import com.tp.util.Page;
import com.tp.util.ReflectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.*;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HibernateDao<T> extends HibernateDaoSupport {
protected Class<T> entityClass;
protected Logger logger = Logger.getLogger(HibernateDao.class);
/**
* <li>通过类属性操作对应的对象</li>
*
*/
public HibernateDao() {
this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass());
}
/**
* 保存新增或修改的对象.
*/
public void save(final T entity) {
Assert.notNull(entity, "entity不能为空");
currentSession().saveOrUpdate(entity);
logger.debug("save entity: {}" + entity.toString());
}
/**
* 保存或新增 返回操作对象
* @param obj
* @return
*/
public Object saveUpdate(Object obj) {
return currentSession().merge(obj);
}
/**
* 方法将修改表中记录,其所需要的实体状态为脱管状态
*/
public void merge(final T entity) {
Assert.notNull(entity, "entity不能为空");
currentSession().merge(entity);
logger.debug("merge entity: {}" + entity.toString());
}
/**
* 删除对象.
*
* @param entity 对象必须是session中的对象或含id属性的transient对象.
*/
public void delete(final T entity) {
Assert.notNull(entity, "entity不能为空");
currentSession().delete(entity);
logger.debug("delete entity: {}" + entity.toString());
}
/**
* 按id删除对象.
*/
public void delete(Serializable id) {
Assert.notNull(id, "id不能为空");
delete(get(id));
logger.debug("delete entity {},id is {}" + entityClass.getSimpleName() + " id: " + id);
}
/**
* 按id获取对象.
*/
public T get(Serializable id) {
Assert.notNull(id, "id不能为空");
return (T) currentSession().get(entityClass, id);
}
/**
* 获取全部对象.
*/
public List<T> getAll() {
return find();
}
/**
* 获取全部对象,支持排序.
*/
public List<T> getAll(String orderBy, boolean isAsc) {
Criteria c = createCriteria();
if (isAsc) {
c.addOrder(Order.asc(orderBy));
} else {
c.addOrder(Order.desc(orderBy));
}
return c.list();
}
/**
* 按属性查找对象列表,匹配方式为相等.
*/
public List<T> findBy(final String propertyName, final Object value) {
Assert.hasText(propertyName, "propertyName不能为空");
Criterion criterion = Restrictions.eq(propertyName, value);
return find(criterion);
}
/**
* 按属性查找唯一对象,匹配方式为相等.
*/
public T findUniqueBy(final String propertyName, final Object value) {
Assert.hasText(propertyName, "propertyName不能为空");
Criterion criterion = Restrictions.eq(propertyName, value);
return (T) createCriteria(criterion).uniqueResult();
}
/**
* 按id列表获取对象.
* @param ids id列表
* @return id列表对应的数据对象列表
*/
public List<T> findByIds(List<Serializable> ids) {
return find(Restrictions.in(getIdName(), ids));
}
/**
* 按HQL查询对象列表.
*
* @param values 数量可变的参数,按顺序绑定.
*/
public <X> List<X> find(final String hql, final Object... values) {
return createQuery(hql, values).list();
}
/**
* 按HQL查询对象列表.
*
* @param values 命名参数,按名称绑定.
*/
public <X> List<X> find(final String hql, final Map<String, ?> values) {
return createQuery(hql, values).list();
}
/**
* 按HQL查询唯一对象.
*
* @param values 数量可变的参数,按顺序绑定.
*/
public <X> X findUnique(final String hql, final Object... values) {
return (X) createQuery(hql, values).uniqueResult();
}
/**
* 按HQL查询唯一对象.
*
* @param values 命名参数,按名称绑定.
*/
public <X> X findUnique(final String hql, final Map<String, ?> values) {
return (X) createQuery(hql, values).uniqueResult();
}
/**
* 执行HQL进行批量修改/删除操作.
*/
public int batchExecute(final String hql, final Object... values) {
return createQuery(hql, values).executeUpdate();
}
/**
* 执行HQL进行批量修改/删除操作.
* @return 更新记录数.
*/
public int batchExecute(final String hql, final Map<String, ?> values) {
return createQuery(hql, values).executeUpdate();
}
/**
* 根据查询HQL与参数列表创建Query对象.
*
* 本类封装的find()函数全部默认返回对象类型为T,当不为T时使用本函数.
*
* @param values 数量可变的参数,按顺序绑定.
*/
public Query createQuery(final String queryString, final Object... values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = currentSession().createQuery(queryString);
if (values != null) {
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
}
return query;
}
/**
* 执行带输出参数存储过程
* @param callSql
* @param inParameters
*/
public String[] prepareCallAndReturn(final String callSql, final Integer inNumber, final Integer outNumber, final Object... inParameters){
Session session = currentSession();
return session.doReturningWork(new ReturningWork<String[]>() {
public String[] execute(Connection connection) throws SQLException {
String[] outRest = new String[outNumber];
CallableStatement cs = connection.prepareCall(callSql);
// int inParametersLength = inParameters.length;
for(int i=0;i<inNumber;i++){
cs.setObject(i+1, inParameters[i]);
}
for(int i=0;i<outNumber;i++){
cs.registerOutParameter(inNumber+i+1,Types.VARCHAR);
}
cs.executeUpdate();
for(int i=0;i<outNumber;i++){
outRest[i] = cs.getString(inNumber+i+1);
}
return outRest;
}
});
}
/**
* 根据查询HQL与参数列表创建Query对象.
*
* @param values 命名参数,按名称绑定.
*/
public Query createQuery(final String queryString, final Map<String, ?> values) {
Assert.hasText(queryString, "queryString不能为空");
Query query = currentSession().createQuery(queryString);
if (values != null) {
query.setProperties(values);
}
return query;
}
/**
* 按Criteria查询对象列表.
*
* @param criterions 数量可变的Criterion.
*/
public List<T> find(final Criterion... criterions) {
return createCriteria(criterions).list();
}
/**
* 按Criteria查询唯一对象.
*
* @param criterions 数量可变的Criterion.
*/
public T findUnique(final Criterion... criterions) {
return (T) createCriteria(criterions).uniqueResult();
}
/**
* 根据Criterion条件创建Criteria.
*
* 本类封装的find()函数全部默认返回对象类型为T,当不为T时使用本函数.
*
* @param criterions 数量可变的Criterion.
*/
public Criteria createCriteria(final Criterion... criterions) {
Criteria criteria = currentSession().createCriteria(entityClass);
for (Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}
/**
* 初始化对象.
* 使用load()方法得到的仅是对象Proxy, 在传到View层前需要进行初始化.
* 只初始化entity的直接属性,但不会初始化延迟加载的关联集合和属性.
* 如需初始化关联属性,可实现新的函数,执行:
* Hibernate.initialize(user.getRoles()),初始化User的直接属性和关联集合.
* Hibernate.initialize(user.getDescription()),初始化User的直接属性和延迟加载的Description属性.
*/
public void initEntity(T entity) {
Hibernate.initialize(entity);
}
/**
* @see #initEntity(Object)
*/
public void initEntity(List<T> entityList) {
for (T entity : entityList) {
Hibernate.initialize(entity);
}
}
/**
* 为Query添加distinct transformer.
*/
public Query distinct(Query query) {
query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return query;
}
/**
* 为Criteria添加distinct transformer.
*/
public Criteria distinct(Criteria criteria) {
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
return criteria;
}
/**
* 取得对象的主键名.
*/
public String getIdName() {
ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass);
return meta.getIdentifierPropertyName();
}
/*
*//**
* 分页获取全部对象.
*//*
public Page<T> getAll(final Page<T> page) {
return findPage(page);
}*/
/**
* 按HQL分页查询.
*
* @param page 分页参数.
* @param hql hql语句.
*
* @return 分页查询结果, 附带结果列表及所有查询时的参数.
// */
// @SuppressWarnings("unchecked")
// public Page<T> findPage(final Page<T> page, final String hql) {
// Assert.notNull(page, "page不能为空");
//
// Query q = createQuery(hql);
//
// if (page.isAutoCount()) {
// long totalCount = countHqlResult(hql, null);
// page.setTotalCount(totalCount);
// }
//
// setPageParameter(q, page);
//
// List<T> result = q.list();
// if(result.size() == 0 && page.getPageNo() > 1){
// page.setPageNo(page.getPrePage());
// setPageParameter(q, page);
// result = q.list();
// }
//
// page.setResult(result);
// return page;
// }
/**
* 按HQL分页查询.
*
* @param page 分页参数.
* @param hql hql语句.
* @param values 命名参数,按名称绑定.
*
* @return 分页查询结果, 附带结果列表及所有查询时的参数.
*/
// @SuppressWarnings("unchecked")
// public Page<T> findPage(final Page<T> page, final String hql, final Map<String, ?> values) {
// Assert.notNull(page, "page不能为空");
//
// Query q = createQuery(hql, values);
//
// if (page.isAutoCount()) {
// long totalCount = countHqlResult(hql, values);
// page.setTotalCount(totalCount);
// }
//
// setPageParameter(q, page);
//
// List<T> result = q.list();
// if(result.size() == 0 && page.getPageNo() > 1){
// page.setPageNo(page.getPrePage());
// setPageParameter(q, page);
// result = q.list();
// }
//
// page.setResult(result);
// return page;
// }
/* *//**
* 按Criteria分页查询.
*
* @param page 分页参数.
* @param criterions 数量可变的Criterion.
*
* @return 分页查询结果.附带结果列表及所有查询时的参数.
*//*
@SuppressWarnings("unchecked")
public Page<T> findPage(final Page<T> page, final Criterion... criterions) {
Assert.notNull(page, "page不能为空");
Criteria c = createCriteria(criterions);
if (page.isAutoCount()) {
int totalCount = countCriteriaResult(c);
page.setTotalCount(totalCount);
}
setPageParameter(c, page);
List<T> result = c.list();
if(result.size() == 0 && page.getPageNo() > 1){
page.setPageNo(page.getPrePage());
setPageParameter(c, page);
result = c.list();
}
page.setResult(result);
return page;
}
*/
/* *//**
* 将实体中的属性作为过滤条件分页查找对象。
* @param page
* @param entity
* @return 分页对象Page<T>
*//*
public Page<T> findPage(final Page<T> page, T entity){
Criterion[] criterions = paraseObject(entity);
return findPage(page, criterions);
}*/
/* *//**
* 执行count查询获得本次Criteria查询所能获得的对象总数.
*//*
@SuppressWarnings("unchecked")
protected int countCriteriaResult(final Criteria c) {
CriteriaImpl impl = (CriteriaImpl) c;
// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
Projection projection = impl.getProjection();
ResultTransformer transformer = impl.getResultTransformer();
List<CriteriaImpl.OrderEntry> orderEntries = null;
try {
orderEntries = (List<CriteriaImpl.OrderEntry>) ReflectionUtils.getFieldValue(impl, "orderEntries");
ReflectionUtils.setFieldValue(impl, "orderEntries", new ArrayList<CriteriaImpl.OrderEntry>());
} catch (Exception e) {
logger.error("不可能抛出的异常:{}", e);
}
// 执行Count查询
int totalCount = (Integer) c.setProjection(Projections.rowCount()).uniqueResult();
// 将之前的Projection,ResultTransformer和OrderBy条件重新设回去
c.setProjection(projection);
if (projection == null) {
c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
if (transformer != null) {
c.setResultTransformer(transformer);
}
try {
ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
} catch (Exception e) {
logger.error("不可能抛出的异常:{}", e);
}
return totalCount;
}*/
/**
* 设置分页参数到Criteria对象,辅助函数.
*/
// protected Criteria setPageParameter(final Criteria c, final Page<T> page) {
// //hibernate的firstResult的序号从0开始
// c.setFirstResult(page.getFirst() - 1);
// c.setMaxResults(page.getPageSize());
//
// if (page.isOrderBySetted()) {
// String[] orderByArray = StringUtils.split(page.getOrderBy(), ',');
// String[] orderArray = StringUtils.split(page.getOrder(), ',');
//
// Assert.isTrue(orderByArray.length == orderArray.length, "分页多重排序参数中,排序字段与排序方向的个数不相等");
//
// for (int i = 0; i < orderByArray.length; i++) {
// if (Page.ASC.equals(orderArray[i])) {
// c.addOrder(Order.asc(orderByArray[i]));
// } else {
// c.addOrder(Order.desc(orderByArray[i]));
// }
// }
// }
// return c;
// }
/**
* 设置分页参数到Query对象,辅助函数.
*/
// protected Query setPageParameter(final Query q, final Page<T> page) {
// //hibernate的firstResult的序号从0开始
// q.setFirstResult(page.getFirst() - 1);
// q.setMaxResults(page.getPageSize());
// return q;
// }
/**
* 执行count查询获得本次Hql查询所能获得的对象总数.
*
* 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
*/
protected long countHqlResult(final String hql, final Map<String, ?> values) {
String fromHql = hql;
//select子句与order by子句会影响count查询,进行简单的排除.
fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
fromHql = StringUtils.substringBefore(fromHql, "order by");
String countHql = "select count(*) " + fromHql;
try {
Long count = findUnique(countHql, values);
return count;
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
}
}
/**
* 将对象中的get方法中的不为空值的属性转化成Criterion数组
* @param entity
* @return Criterion数组
*/
public Criterion[] paraseObject(Object entity){
if(entity == null) {
//throw new Exception("查询条件对象为空");
return null;
}
List<Criterion> criterionList = new ArrayList<Criterion>();
try{
Method objectMethods[] = entity.getClass().getMethods();
int k = 1;
for(int i = 0; i < objectMethods.length; i++) {
String methodName = objectMethods[i].getName();
if(methodName.startsWith("get") && !methodName.equals("getClass") && !methodName.endsWith("Str")){
Object fieldValue = objectMethods[i].invoke(entity);
String fieldType = objectMethods[i].getReturnType().getName();
if(fieldValue != null
&& ((fieldType.equals("java.lang.String") && fieldValue.toString().length() != 0)
|| ( (fieldType.equals("long") ||fieldType.equals("int") ||fieldType.equals("java.lang.Integer") ||fieldType.equals("java.lang.Long")
||fieldType.equals("double") ||fieldType.equals("java.lang.Double")
||fieldType.equals("float"))
&& Double.parseDouble(fieldValue.toString()) != 0)
|| fieldType.equals("java.sql.Date") ) )
{
String fieldName = methodToAttr(methodName);
if(fieldValue.toString().startsWith("%") && fieldValue.toString().endsWith("%")){
criterionList.add(Restrictions.like(fieldName, fieldValue.toString(), MatchMode.ANYWHERE));
}else if(fieldValue.toString().startsWith("%")){
criterionList.add(Restrictions.like(fieldName, fieldValue.toString(), MatchMode.START));
}else if(fieldValue.toString().endsWith("%")){
criterionList.add(Restrictions.like(fieldName, fieldValue.toString(), MatchMode.END));
}else if(fieldValue.toString().startsWith("NOTEQUAL ")){
String tempStr = fieldValue.toString().replaceAll("NOTEQUAL ", "");
String[] tempStrs = tempStr.split(",");
for(int m = 0; m < tempStrs.length; m++){
criterionList.add(Restrictions.not(Restrictions.eq(fieldName, tempStrs[m])));
}
} else {
criterionList.add(Restrictions.eq(fieldName, fieldValue));
}
k++;
}
}
}
}catch(Exception ex) {
ex.printStackTrace();
}
return criterionList.toArray(new Criterion[criterionList.size()]);
}
/**
* 将方法名转成对象,即把get去除,并将首字母转成小写。
* @param methodName
* @return
* @throws Exception
*/
private String methodToAttr(String methodName) throws Exception{
try {
String s = methodName.substring(3, methodName.length());
s = s.toLowerCase();
s = s.substring(0, 1) + methodName.substring(4, methodName.length());
return s;
}catch(Exception ex){
throw ex;
}
}
/**
* <li>HibernateDaoSupport默认sessionFactory不能注入</li>
* @author dongkun
*/
@Autowired
public void setMySessionFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
/**
* 将封装的datemodel按照其分页参数进行结果获取(List)。
* @param countHql 符合查询条件个数hql
* @param queryHql 符合查询条件内容hql
* @param dgm 封装前台页面传递的查询参数
* @return 总个数 以及 分页的显示内容
* @throws Exception
*/
protected Map<String, Object> getObjectDateModel(String countHql,String queryHql,DataGridModel dgm)throws Exception{
Map<String, Object> result = new HashMap<String, Object>(2);
Query queryTotal = currentSession().createQuery(countHql);
Query queryList = currentSession().createQuery(queryHql)
.setFirstResult((dgm.getPage() - 1) * dgm.getRows()).setMaxResults(dgm.getRows());
int total = ((Long)queryTotal.uniqueResult()).intValue(); //这里必须先转成Long再取intValue,不能转成Integer
List list = queryList.list();
result.put("total", total);
result.put("rows", list);
return result;
}
}