package cn.sunsharp.ycpn.core.dao.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityNotFoundException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.OrderEntry;
import org.hibernate.transform.ResultTransformer;
import org.skyway.spring.util.dao.AbstractJpaDao;
import org.springframework.transaction.annotation.Transactional;
import cn.sunsharp.ycpn.core.Page;
import cn.sunsharp.ycpn.core.ReflectionUtils;
import cn.sunsharp.ycpn.core.dao.BaseDAO;
/**
*
* <p>Title: BaseDAOImpl.java</p>
*
* <p>Description: 抽象泛型dao,entityManager由子类注入</p>
*
* <p>Datetime: 2011-12-25 下午5:39:22</p>
*
* @company 成都映潮科技有限公司
*
* @author <a href="mailto:liwei@sunsharp.cn">p.k.ripper</a>
*
*/
public abstract class BaseDAOImpl<T, PK extends Serializable> extends AbstractJpaDao<T> implements BaseDAO<T,PK>{
protected Logger log = Logger.getLogger(this.getClass());
protected Class<T> entityClass=ReflectionUtils.getSuperClassGenricType(getClass());
private final Set<Class<?>> dataTypes = new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { entityClass }));
public BaseDAOImpl() {
setDefaultMaxResults(-1);
}
@Override
public Set<Class<?>> getTypes() {
return dataTypes;
}
/**
* 如有必要,重写此方法,return true;
*/
@Override
public boolean canBeMerged(T o) {
return false;
}
@Override
public T saveEntity(T e) throws Exception{
return store(e);
}
@Override
public T updateEntity(T e) throws Exception{
return merge(e);
}
@Override
public void deleteEntity(T e) throws Exception {
remove(e);
}
@Override
public void deleteEntity(final PK id) throws Exception{
T entity=findEntityById(id);
if(null!=entity)deleteEntity(entity);
}
@Transactional
@Override
public T findEntityById(final PK id) throws Exception{
try{
return getEntityManager().find(entityClass, id);
}catch(Exception e){
log.error(e.getMessage());
e.printStackTrace();
return null;
}
}
/**
* 按ID查询多个对象
*
* @param ids
* @return
*/
@Override
public List<T> findByIds(final Collection<PK> ids) throws Exception{
List<T> list=new ArrayList<T>();
if(null!=ids){
if(ids instanceof java.util.Collection){
for(Iterator<PK> i=((Collection<PK>) ids).iterator();i.hasNext();){
T entity=findEntityById(i.next());
if(null!=entity){
list.add(entity);
}
}
}
}
return list;
}
@Override
public void batchSave(Collection<T> e) throws Exception {
if (null!=e) {
if (e instanceof java.util.Collection) {
for (Iterator<T> i = ((Collection<T>) e).iterator(); i.hasNext();) {
try {
store(i.next());
} catch (EntityNotFoundException x) {
// This entity has been deleted - remove it from the collection
i.remove();
}
}
}
}
}
@Override
public void batchUpdate(Collection<T> e) throws Exception {
if (e != null) {
if (e instanceof java.util.Collection) {
for (Iterator<T> i = ((Collection<T>) e).iterator(); i.hasNext();) {
try {
merge(i.next());
} catch (EntityNotFoundException x) {
// This entity has been deleted - remove it from the collection
i.remove();
}
}
}
}
}
@Override
public void batchDelete(Collection<T> e) throws Exception {
if (e != null) {
if (e instanceof java.util.Collection) {
for (Iterator<T> i = ((Collection<T>) e).iterator(); i.hasNext();) {
try {
remove(i.next());
} catch (EntityNotFoundException x) {
// This entity has been deleted - remove it from the collection
i.remove();
}
}
}
}
}
@Override
public void batchDelete(final PK... ids) throws Exception {
for (int i = 0; i < ids.length; i++) {
try{
T entity=findEntityById(ids[i]);
if(null!=entity){
deleteEntity(entity);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
protected Session getSession(){
Session session=(Session)getEntityManager().getDelegate();
return session;
}
@Override
public Page<T> findPage(final Page<T> page, final String hql, final Object... parameters)
throws Exception {
List<T> result = executeQuery(hql, page.getFirst(), page.getPageSize(), parameters);
if(page.isAutoCount()){
long totoal=countHqlResult(hql,parameters);
page.setTotal(totoal);
}
page.setRows(result);
return page;
}
@SuppressWarnings("unchecked")
public List<Object> findPageBySQL(final Page<T> page,String sql,Object...parameters)throws Exception{
Query query = getSession().createSQLQuery(sql).addEntity(entityClass)
.setFirstResult(page.getFirst()).setMaxResults(page.getPageSize());
if(null!=parameters && parameters.length>0){
for (int i = 0; i < parameters.length; i++) {
query = query.setParameter(i, parameters[i]);
}
}
List<Object> result = query.list();
return result;
}
public Object findSingleResultBySQL(String sql,Object...parameters)throws Exception{
Query query = getSession().createSQLQuery(sql);
if(null!=parameters && parameters.length>0){
for (int i = 0; i < parameters.length; i++) {
query = query.setParameter(i, parameters[i]);
}
}
Object object = query.uniqueResult();
return object;
}
@Override
public Page<T> findPageByNameQuery(final Page<T> page,final String queryName,final Object... parameters) throws Exception{
List<T> result=this.executeQueryByName(queryName, page.getFirst(), page.getPageSize(), parameters);
page.setRows(result);
return page;
}
/**
* 执行count查询获得本次Hql查询所能获得的对象总数.
*
* 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
*/
protected long countHqlResult(final String hql, final Object... parameters) {
String countHql = prepareCountHql(hql);
try {
Long count = findUniqueCountByHql(countHql, parameters);
return count;
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:"
+ countHql, e);
}
}
/**
* 执行count查询获得本次Sql查询所能获得的对象总数.
*
* 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询.
*/
protected long countSqlResult(final String sql, final Object... parameters) {
String countHql = prepareCountHql(sql);
try {
Long count = findUniqueCountByHql(countHql, parameters);
return count;
} catch (Exception e) {
throw new RuntimeException("hql can't be auto count, hql is:"
+ countHql, e);
}
}
private String prepareCountHql(String orgHql) {
String fromHql = orgHql;
fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
fromHql = StringUtils.substringBefore(fromHql, "order by");
String countHql = "select count(*) " + fromHql;
return countHql;
}
@Override
@SuppressWarnings("unchecked")
public <X> X findUniqueCountByHql(String hql, Object... parameters)
throws Exception {
return (X) executeQuerySingleResult(hql, parameters);
}
/**
* 按Criteria分页查询.
*
* @param page 分页参数.
* @param criterions 数量可变的Criterion.
*
* @return 分页查询结果.附带结果列表及所有查询输入参数.
*/
@Override
@SuppressWarnings("unchecked")
public Page<T> findAllByPage(final Page<T> page,final Criterion... criterions) throws Exception {
Criteria c = createCriteria(criterions);
if (page.isAutoCount()) {
long totalCount = countCriteriaResult(c);
page.setTotal(totalCount);
}
setPageParameterToCriteria(c, page);
List<T> result = c.list();
page.setRows(result);
return page;
}
/**
* 按Criteria分页查询.
*
* @param page 分页参数.
* @param criterions 数量可变的Criterion.
*
* @return 分页查询结果.附带结果列表及所有查询输入参数.
*/
@Override
@SuppressWarnings("unchecked")
public Page<T> findAllByPageDistinct(final Page<T> page,final Criterion... criterions) throws Exception {
Criteria c = createCriteria(criterions);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
if (page.isAutoCount()) {
long totalCount = countCriteriaResult(c);
page.setTotal(totalCount);
}
setPageParameterToCriteria(c, page);
List<T> result = c.list();
page.setRows(result);
return page;
}
protected Criteria createCriteria(final Criterion... criterions) {
Session session=getSession();
Criteria criteria = session.createCriteria(entityClass);
for (Criterion c : criterions) {
if(null!=c)criteria.add(c);
}
return criteria;
}
/**
* 设置分页参数到Criteria对象,辅助函数.
*/
protected Criteria setPageParameterToCriteria(final Criteria c,
final Page<T> page) {
c.setFirstResult(page.getFirst() );
c.setMaxResults(page.getPageSize());
if (page.isOrderBySetted()) {
String[] orderByArray = StringUtils.split(page.getOrderBy(), ',');
String[] orderArray = StringUtils.split(page.getOrder(), ',');
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;
}
/**
* 执行count查询获得本次Criteria查询所能获得的对象总数.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected long 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<OrderEntry>) ReflectionUtils.getFieldValue(impl,"orderEntries");
ReflectionUtils.setFieldValue(impl, "orderEntries", new ArrayList());
} catch (Exception e) {
log.error("不可能抛出的异常:" + e.getMessage());
}
// 执行Count查询
Long totalCountObject = (Long) c.setProjection(Projections.rowCount())
.uniqueResult();
long totalCount = (totalCountObject != null) ? totalCountObject : 0;
// 将之前的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) {
log.error("不可能抛出的异常:" + e.getMessage());
}
return totalCount;
}
@SuppressWarnings("unchecked")
@Override
public List<T> findByProperty(Map<String, Object> values) throws Exception {
Criterion criterion = Restrictions.allEq(values);
Criteria criteria = createCriteria();
criteria.add(criterion);
return criteria.list();
}
@Override
public List<T> findByPropertyLike(String propertyName, Object value)
throws Exception {
Criterion criterion = Restrictions.like(propertyName, (String)value,MatchMode.ANYWHERE);
return findByCriteria(criterion);
}
@Override
public List<T> findByProperty(String propertyName, Object value)
throws Exception {
Criterion criterion = Restrictions.eq(propertyName, value);
return findByCriteria(criterion);
}
@Override
@SuppressWarnings("unchecked")
public List<T> findByCriteria(Criterion... criterions) {
return createCriteria(criterions).list();
}
@Override
@SuppressWarnings("unchecked")
public List<T> findByCriteria(Order[] order,Criterion... criterions){
Criteria ct=createCriteria(criterions);
for(Order o:order){
if(null!=o)ct.addOrder(o);
}
return ct.list();
}
}