package com.ifish.hibernate;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * hibernate DAO基类
 * @author ggw
 * @param <T>
 * @param <ID>
 */
public abstract class HibernateBaseDao<T, ID extends Serializable> {

	@Autowired
	protected SessionFactory sessionFactory;

	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 根据ID查找
	 * @param id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T get(ID id) {
		return (T) getSession().get(getEntityClass(), id);
	}
	
	/**
	 * 保存
	 * @param id
	 * @return
	 */
	public T save(T t) {
		getSession().save(t);
		return t;
	}
	
	/**
	 * 更新
	 * @param id
	 * @return
	 */
	public T update(T t) {
		getSession().update(t);
		return t;
	}
	
	/**
	 * 保存或更新
	 * @param id
	 * @return
	 */
	public T saveOrUpdate(T t) {
		getSession().saveOrUpdate(t);
		return t;
	}
	
	/**
	 * 删除
	 * @param id
	 * @return
	 */
	public void delete(T t) {
		getSession().delete(t);
	}
	
	/**
	 * 按属性查找对象列表
	 * @param criterions
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(Criterion... criterions) {
		Criteria cri = createCriteria(null,criterions);
		return cri.list();
	}
	
	/**
	 * 按属性查找对象列表
	 * @param criterions
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(Order order,Criterion... criterions) {
		Criteria cri = createCriteria(order,criterions);
		return cri.list();
	}

	/**
	 * 按属性查找唯一对象
	 * @param criterions
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T findUniqueByProperty(Criterion... criterions) {
		Criteria cri = createCriteria(null,criterions);
		return (T) cri.uniqueResult();
	}

	/**
	 * 按属性统计记录数
	 * @param criterion
	 * @return
	 */
	public int countByProperty(Criterion... criterion) {
		return ((Number) (this.createCriteria(null,criterion).setProjection(Projections.rowCount()).uniqueResult())).intValue();
	}
	
	/**
	 * 按Criterion查询分页列表数据.
	 * @param firstResult
	 * @param pageSize
	 * @param criterion
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Pagination<T> findByCriteria(Integer firstResult,Integer pageSize,Order order,Criterion... criterion) {
		Criteria criteria = createCriteria(order,criterion);
		if(firstResult!=null && pageSize!=null){
			criteria.setFirstResult(firstResult);
			criteria.setMaxResults(pageSize);
		}
		Pagination<T> page = new Pagination<T>();
		page.setTotalCount(this.countByProperty(criterion));
		page.setList(criteria.list());
		return page;
	}

	/**
	 * 根据Criterion条件创建Criteria,后续可进行更多处理,辅助函数.
	 * @param criterions
	 * @return
	 */
	protected Criteria createCriteria(Order order,Criterion... criterions) {
		Criteria criteria = getSession().createCriteria(getEntityClass());
		//筛选条件
		for (Criterion c : criterions) {
			criteria.add(c);
		}
		//排序
		if(order!=null){
			criteria.addOrder(order);
		}
		return criteria;
	}
	
	/**
	 * 获得Dao对于的实体类
	 * @return
	 */
	abstract protected Class<T> getEntityClass();
	
}
