package cn.estsh.i3plus.pojo.base.jpa.daoimpl;

import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.codemaker.SnowflakeIdMaker;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.jpa.dao.BaseRepository;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.NonUniqueResultException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @Description : 自定义持久化接口实现
 * @Reference :
 * @Author : alwaysfrin
 * @CreateDate : 2018-09-13 11:24
 * @Modify:
 **/
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
        implements BaseRepository<T, ID> {
    public static final Logger LOGGER = LoggerFactory.getLogger(BaseRepositoryImpl.class);

    /**
     * 持久化上下文
     */
    private final EntityManager entityManager;

    private Class<T> persistentClass;
    private SnowflakeIdMaker snowflakeIdMaker;
    /* 默认查询数据条数 */
    private static final Pager DEFAULT_PAGER = new Pager(10,10);
    private static final Pager GETBYPROPERTY_PAGER = new Pager(1,1);

    public BaseRepositoryImpl(Class<T> clz, EntityManager em, SnowflakeIdMaker snowflakeIdMaker) {
        super(clz, em);
        this.entityManager = em;
        this.persistentClass = clz;
        this.snowflakeIdMaker = snowflakeIdMaker;
    }

    public void clearSession(){
        entityManager.clear();
    }

    public void detachObject(T t){
        if (t == null) {
            return;
        }
        entityManager.detach(t);
    }

    //集合设置为游离态
    public void detachList(List<T> list){
        if(list != null){
            for(T t : list) {
                //设置对象为游离态
                entityManager.detach(t);
            }
        }
    }

    private void setParameter(Query query, String[] propName, Object[] propValue) {
        String name = null;
        Object value = null;
        for (int i = 0; i < propName.length; i++) {
            name = propName[i];
            value = propValue[i];
            if (value != null) {
                if ((value instanceof Object[])) {
                    query.setParameter(name.replace(".", ""), (Object[]) value);
                } else if ((value instanceof Collection)) {
                    query.setParameter(name.replace(".", ""), (Collection) value);
                } else {
                    query.setParameter(name.replace(".", ""), value);
                }
            }
        }
    }

    private void appendQL(StringBuffer sb, String[] propName, Object[] propValue) {
        String name = null;
        Object value = null;
        for (int i = 0; i < propName.length; i++) {
            name = propName[i];
            value = propValue[i];
            if (((value instanceof Object[])) || ((value instanceof Collection))) {
                Object[] arraySerializable = (Object[]) value;
                if ((arraySerializable != null) && (arraySerializable.length > 0)) {
                    sb.append(" and model." + name + " in (:" + name.replace(".", "") + ")");
                }
            } else if (value == null) {
                sb.append(" and model." + name + " is null ");
            } else {
                sb.append(" and model." + name + "=:" + name.replace(".", ""));
            }
        }
    }

    @Override
    public T insert(T item) {
        return insert(item, true);
    }

    @Override
    public T insert(T item, boolean initParam) {
        return innerSave(item, initParam);
    }

    @Override
    public <S extends T> S save(S entity) {
        //复写save方法，若id为0或空则新增，不然则修改
        return (S) innerSave(entity, true);
    }

    @Override
    public void update(Object... item) {
        if (null != item) {
            for (Object entity : item) {
                entityManager.merge(entity);
            }
        }
    }

    @Override
    public int executeUpdate(String qlString, Object... values) {
        Query query = entityManager.createQuery(qlString);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i + 1, values[i]);
            }
        }
        return query.executeUpdate();
    }

    @Override
    public int executeUpdate(String qlString, Map<String, Object> params) {
        Query query = entityManager.createQuery(qlString);
        for (String name : params.keySet()) {
            query.setParameter(name, params.get(name));
        }
        return query.executeUpdate();
    }

    @Override
    public int executeUpdate(String qlString, List<Object> values) {
        Query query = entityManager.createQuery(qlString);
        for (int i = 0; i < values.size(); i++) {
            query.setParameter(i + 1, values.get(i));
        }
        return query.executeUpdate();
    }

    @Override
    public void deleteById(ID id) {
        deleteByProperty("id", id);
    }

    @Override
    public int deleteByProperty(String propName, Object propValue) {
        return deleteByProperties(new String[]{propName}, new Object[]{propValue});
    }

    @Override
    public int deleteByProperties(String[] propName, Object[] propValue) {
        if ((propName != null) && (propName.length > 0) && (propValue != null) && (propValue.length > 0) && (propValue.length == propName.length)) {
            StringBuffer sb = new StringBuffer("delete from " + persistentClass.getName() + " model where 1=1 ");
            appendQL(sb, propName, propValue);
            Query query = entityManager.createQuery(sb.toString());
            setParameter(query, propName, propValue);

            return query.executeUpdate();
        } else {
            throw new IllegalArgumentException("删除错误!propName:" + propName + ",propValue:" + propValue);
        }
    }

    @Override
    public int deleteByIds(ID[] ids) {
        return deleteByPropertyIn("id", ids);
    }

    @Override
    public int deleteByPropertyIn(String propName, Object[] propValues) {
        if ((propName != null && propName.length() > 0) && (propValues != null && propValues.length > 0)) {
            String hql = "delete from " + persistentClass.getName() + " model where model." + propName + " in(:" + propName + ") ";
            Query query = entityManager.createQuery(hql);
            query.setParameter(propName, Arrays.asList(propValues));

            return query.executeUpdate();
        } else {
            throw new IllegalArgumentException("删除出错：" + propName + ":" + propValues);
        }
    }

    @Override
    public int updateByProperties(String conditionName, Object conditionValue, String propertyName, Object propertyValue) {
        return updateByProperties(new String[]{conditionName}, new Object[]{conditionValue}, new String[]{propertyName}, new Object[]{propertyValue});
    }

    @Override
    public int updateByProperties(String conditionName, Object conditionValue, String[] propertyName, Object[] propertyValue) {
        return updateByProperties(new String[]{conditionName}, new Object[]{conditionValue}, propertyName, propertyValue);
    }

    @Override
    public int updateByProperties(String[] conditionName, Object[] conditionValue, String propertyName, Object propertyValue) {
        return updateByProperties(conditionName, conditionValue, new String[]{propertyName}, new Object[]{propertyValue});
    }

    @Override
    public int updateByProperties(String[] conditionName, Object[] conditionValue, String[] propertyName, Object[] propertyValue) {
        return updateByPropertiesMain(conditionName, conditionValue, propertyName, propertyValue, true);
    }

    @Override
    public int updateByPropertiesWithVal(String conditionName, Object conditionValue, String propertyName, Object propertyValue) {
        return updateByPropertiesWithVal(new String[]{conditionName}, new Object[]{conditionValue}, new String[]{propertyName}, new Object[]{propertyValue});
    }

    @Override
    public int updateByPropertiesWithVal(String conditionName, Object conditionValue, String[] propertyName, Object[] propertyValue) {
        return updateByPropertiesWithVal(new String[]{conditionName}, new Object[]{conditionValue}, propertyName, propertyValue);
    }

    @Override
    public int updateByPropertiesWithVal(String[] conditionName, Object[] conditionValue, String propertyName, Object propertyValue) {
        return updateByPropertiesWithVal(conditionName, conditionValue, new String[]{propertyName}, new Object[]{propertyValue});
    }

    @Override
    public int updateByPropertiesWithVal(String[] conditionName, Object[] conditionValue, String[] propertyName, Object[] propertyValue) {
        return updateByPropertiesMain(conditionName, conditionValue, propertyName, propertyValue, false);
    }

    /**
     * 更新参数汇总方法
     *
     * @param conditionName  条件属性名
     * @param conditionValue 条件属性值
     * @param propertyName   更新属性名
     * @param propertyValue  更新属性值
     * @param valWithSimple  是否简单赋值
     *                       true为正常eg： price = :price
     *                       false为自身添加eg： price = price + :price
     * @return
     */
    private int updateByPropertiesMain(String[] conditionName, Object[] conditionValue,
                                       String[] propertyName, Object[] propertyValue, boolean valWithSimple) {
        if ((propertyName != null) && (propertyName.length > 0) && (propertyValue != null)
                && (propertyValue.length > 0) && (propertyName.length == propertyValue.length)
                && (conditionValue != null) && (conditionValue.length > 0)) {
            StringBuffer sb = new StringBuffer();

            sb.append("update " + persistentClass.getName() + " model set ");
            for (int i = 0; i < propertyName.length; i++) {
                if (valWithSimple) {
                    sb.append(propertyName[i] + " = :p_" + propertyName[i] + ",");
                } else {
                    sb.append(propertyName[i] + " = " + propertyName[i] + " + :p_" + propertyName[i] + ",");
                }
            }
            sb.deleteCharAt(sb.length() - 1);

            sb.append(" where 1=1 ");
            appendQL(sb, conditionName, conditionValue);
            Query query = entityManager.createQuery(sb.toString());
            for (int i = 0; i < propertyName.length; i++) {
                query.setParameter("p_" + propertyName[i], propertyValue[i]);
            }

            setParameter(query, conditionName, conditionValue);
            return query.executeUpdate();
        } else {
            throw new IllegalArgumentException("参数值错误!conditionName:" + conditionName
                    + ",conditionValue:" + conditionValue + ",propertyName:" + propertyName + ",propertyValue:" + propertyValue);
        }
    }

    @Override
    public int updateByProperties(String propertyName, Object propertyValue, DdlPackBean packBean) {
        return updateByProperties(new String[]{propertyName}, new Object[]{propertyValue}, packBean);
    }

    @Override
    public int updateByProperties(String[] propertyName, Object[] propertyValue, DdlPackBean packBean) {
        return updateByPropertiesDdlPack(propertyName, propertyValue, packBean, true);
    }

    @Override
    public int updateByPropertiesWithVal(String propertyName, Object propertyValue, DdlPackBean packBean) {
        return updateByPropertiesWithVal(new String[]{propertyName}, new Object[]{propertyValue}, packBean);
    }

    @Override
    public int updateByPropertiesWithVal(String[] propertyName, Object[] propertyValue, DdlPackBean packBean) {
        return updateByPropertiesDdlPack(propertyName, propertyValue, packBean, false);
    }

    private int updateByPropertiesDdlPack(String[] propertyName, Object[] propertyValue,
                                          DdlPackBean packBean, boolean valWithSimple) {
        if ((propertyName != null) && (propertyName.length > 0) && (propertyValue != null)
                && (propertyValue.length > 0) && (propertyName.length == propertyValue.length)) {
            StringBuffer sb = new StringBuffer();

            sb.append("update " + persistentClass.getName() + " model set ");
            for (int i = 0; i < propertyName.length; i++) {
                if (valWithSimple) {
                    sb.append(propertyName[i] + " = :p_" + propertyName[i] + ",");
                } else {
                    sb.append(propertyName[i] + " = " + propertyName[i] + " + :p_" + propertyName[i] + ",");
                }
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append(" where 1=1 " + packBean.getWhereAppend());

            Query query = entityManager.createQuery(sb.toString());
            //更新值
            for (int i = 0; i < propertyName.length; i++) {
                query.setParameter("p_" + propertyName[i], propertyValue[i]);
            }
            //查询条件
            for (String key : packBean.getHqlPreparedMap().keySet()) {
                query.setParameter("m_" + key, packBean.getHqlPreparedMap().get(key));
            }

            return query.executeUpdate();
        } else {
            throw new IllegalArgumentException("参数值错误!,propertyName:" + propertyName + ",propertyValue:" + propertyValue);
        }
    }

    @Override
    public int updateByHqlWhere(String hqlWhere, String propertyName, Object propertyValue) {
        return updateByHqlWhere(hqlWhere, new String[]{propertyName}, new Object[]{propertyValue});
    }

    @Override
    public int updateByHqlWhere(String hqlWhere, String[] propertyName, Object[] propertyValue) {
        if ((propertyName != null) && (propertyName.length > 0) && (propertyValue != null)
                && (propertyValue.length > 0) && (propertyName.length == propertyValue.length)) {
            StringBuffer sb = new StringBuffer();

            sb.append("update " + persistentClass.getName() + " model set ");
            for (int i = 0; i < propertyName.length; i++) {
                sb.append(propertyName[i] + " = :p_" + propertyName[i] + ",");
            }
            sb.deleteCharAt(sb.length() - 1);

            sb.append(" where 1=1 ");
            sb.append(hqlWhere);
            Query query = entityManager.createQuery(sb.toString());
            for (int i = 0; i < propertyName.length; i++) {
                query.setParameter("p_" + propertyName[i], propertyValue[i]);
            }

            return query.executeUpdate();
        } else {
            throw new IllegalArgumentException("参数值错误! propertyName:" + propertyName + ",propertyValue:" + propertyValue);
        }
    }

    @Override
    public T getById(long id) {
        try {
            return entityManager.find(persistentClass, id);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<T> list() {
        List<T> l = this.findAll();
        this.flush();
        return l;
    }

    @Override
    public List<T> listPager(Pager pager) {
        if (pager != null) {
            return entityManager.createQuery("from " + persistentClass.getName())
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        } else {
            return new ArrayList<T>();
        }
    }

    @Override
    public List<T> list(final String hql) {
        return entityManager.createQuery(hql).getResultList();
    }

    @Override
    public List<T> findByPage(DdlPackBean packBean, int offset, int pageSize) {
        Query query = null;
        String ddl = "from " + persistentClass.getName() + " where 1=1 " + packBean.getPackedHql();

        if (packBean.isHql()) {
            query = entityManager.createQuery(ddl);
        } else {
            query = entityManager.createNativeQuery(ddl);
        }

        for (String key : packBean.getHqlPreparedMap().keySet()) {
            query.setParameter("m_" + key, packBean.getHqlPreparedMap().get(key));
        }

        return query.setFirstResult(offset)
                .setMaxResults(pageSize)
                .getResultList();
    }

    @Override
    public List<T> findByPage(String hql, Object[] values, int offset, int pageSize) {
        Query query = entityManager.createQuery(hql);
        for (int i = 0; i < values.length; i++) {
            query.setParameter(i, values[i]);
        }
        return query.setFirstResult(offset).setMaxResults(pageSize).getResultList();
    }
    @Override
    public List<T> findByProperty(String propertyName, Object value) {
        String queryString = "from " + persistentClass.getSimpleName() + " as model where model." + propertyName + "= :" + propertyName;
        return entityManager.createQuery(queryString).setParameter(propertyName, value).getResultList();
    }
    @Override
    public List<T> findByProperty(String[] propertyNames, Object[] values) {
        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("from " + persistentClass.getSimpleName() + " as model ");

        int size = propertyNames.length;
        if (size > 0) {
            queryString.append("where 1=1 ");
        }

        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        Query queryObject = entityManager.createQuery(queryString.toString());
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }

        return queryObject.getResultList();
    }

    @Override
    public List<T> findByProperty(String propertyName, Object value, String orderByStuff) {
        String queryString = "from " + persistentClass.getSimpleName() + " as model where model." + propertyName + "= :" + propertyName + " " + orderByStuff;
        return entityManager.createQuery(queryString).setParameter(propertyName, value).getResultList();
    }

    @Override
    public List<T> findByProperty(String[] propertyNames, Object[] values, String orderByStuff) {
        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("from " + persistentClass.getSimpleName() + " as model ");

        int size = propertyNames.length;
        if (size > 0) {
            queryString.append("where 1=1 ");
        }

        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        queryString.append(" " + orderByStuff);

        Query queryObject = entityManager.createQuery(queryString.toString());
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }

        return queryObject.getResultList();
    }

    @Override
    public T getByProperty(DdlPackBean packBean) {
        try {
            List<T> list = findByHqlWherePage(packBean,GETBYPROPERTY_PAGER);
            return list != null && list.size() != 0 ? list.get(0) : null;
        }catch(NoResultException ne){
            LOGGER.error("数据不存在，DdlPackBean：{}",packBean);
            return null;
        }catch(NonUniqueResultException ex){
            LOGGER.error("查询单条记录，但出现多条。packBean：{}",packBean);
            throw new RuntimeException("存在多条记录：" + ex.getMessage());
        }
    }

    @Override
    public T getByProperty(String propertyName, Object value) {
        return getByPropertyPager(new String[]{propertyName}, new Object[]{value}, GETBYPROPERTY_PAGER);
    }

    @Override
    public T getByProperty(String[] propertyNames, Object[] values) {
        return getByPropertyPager(propertyNames, values, GETBYPROPERTY_PAGER);
    }

    @Override
    public T getByPropertyPager(String[] propertyNames, Object[] values, Pager pager) {
        pager = pager == null ? GETBYPROPERTY_PAGER: pager;

        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("from " + persistentClass.getSimpleName() + " as model ");

        int size = propertyNames.length;
        if (size > 0) {
            queryString.append("where 1=1 ");
        }

        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        Query queryObject = entityManager.createQuery(queryString.toString());
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }

        try{
            List<T> list = queryObject
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
            return list.size() != 0 ? list.get(0) : null;
        }catch(NoResultException ne){
            LOGGER.error("数据不存在",ne);
            return null;
        }catch(NonUniqueResultException ex){
            LOGGER.error("查询单条记录，但出现多条。",ex);
            throw new RuntimeException("存在多条记录：" + ex.getMessage());
        }
    }

    @Override
    public int listCount() {
        try{
            Long count = entityManager.createQuery("select count(model) from " + persistentClass.getName() + " as model", Long.class)
                    .getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public int findByPropertyCount(String propertyName, Object value) {
        try{
            String queryString = "select count(model) from " + persistentClass.getName() + " as model where model." + propertyName + "= :" + propertyName;
            Long count = entityManager.createQuery(queryString, Long.class)
                    .setParameter(propertyName, value)
                    .getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public T findByVendorNoProperty(String vendorNoStr) {
        List<T>  list=null;
        try {
            if(!StringUtil.isEmpty(vendorNoStr)){
                String queryString = "from " + persistentClass.getSimpleName() + " as model where model.vendorNo= :vendorNo";
                list=entityManager.createQuery(queryString)
                        .setParameter("vendorNo", vendorNoStr)
                        .getResultList();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  list!=null ? list.get(0): null;
    }

    @Override
    public int findByPropertyCount(String[] propertyNames, Object[] values) {
        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("select count(model) from " + persistentClass.getName() + " as model");

        int size = propertyNames.length;
        if (size > 0) {
            queryString.append(" where 1=1 ");
        }

        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        Query queryObject = entityManager.createQuery(queryString.toString(),Long.class);
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }

        try{
            Long count = (Long) queryObject.getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }


    public int findByPropertyCountDemo(String[] propertyNames, Object[] values) {
        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数错误数量和值个数不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("select count(*) from " + persistentClass.getName() + " as model where 1=1 ");
        for (int i = 0; i < propertyNames.length; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        Query queryObject = entityManager.createQuery(queryString.toString(),Long.class);
        for (int i = 0; i < propertyNames.length; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }

        try{
            Long count = (Long) queryObject.getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public List<T> findByPropertyPage(String propertyName, Object value, String orderByStuff, Pager pager) {
        if(pager != null){
            String queryString = "from " + persistentClass.getSimpleName() + " as model where model." + propertyName + "= :" + propertyName + " " + orderByStuff;
            return entityManager.createQuery(queryString)
                    .setParameter(propertyName, value)
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Override
    public List<T> findByPropertyPage(String[] propertyNames, Object[] values, String orderByStuff, Pager pager) {
        if(pager != null){
            if(propertyNames.length != values.length){
                throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
            }
            StringBuffer queryString = new StringBuffer();
            queryString.append("from " + persistentClass.getSimpleName() + " as model ");

            int size = propertyNames.length;
            if (size > 0) {
                queryString.append("where 1=1 ");
            }

            for (int i = 0; i < size; i++) {
                if(values[i] != null) {
                    queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
                }
            }

            if(orderByStuff != null && orderByStuff.length() > 0){
                queryString.append(orderByStuff);
            }

            Query queryObject = entityManager.createQuery(queryString.toString());
            for (int i = 0; i < size; i++) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }

            return queryObject.setFirstResult(pager.getStartRow()).setMaxResults(pager.getPageSize()).getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Deprecated
    @Override
    public List<T> findByHql(String hql) {
        return entityManager.createQuery(hql).getResultList();
    }

    @Deprecated
    @Override
    public List<T> findByHqlWhere(String hqlWhere) {
        StringBuffer queryString = new StringBuffer();
        queryString.append("from " + persistentClass.getSimpleName() + " as model where 1=1 ");

        if (hqlWhere != null && hqlWhere.length() > 0) {
            queryString.append(hqlWhere);
        }

        return entityManager.createQuery(queryString.toString()).getResultList();
    }

    @Override
    public List<T> findByHqlWhere(DdlPackBean packBean) {
        Query query = entityManager.createQuery("from " + persistentClass.getSimpleName()
                + " as model where 1=1 " + packBean.getPackedHql());

        for (String key : packBean.getHqlPreparedMap().keySet()) {
            query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
        }

        return query.getResultList();
    }

    @Override
    public List<T> findByHqlWhere(String hqlWhere, String[] propertyNames, Object[] values, String orderByStuff) {
        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:"
                    + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("from " + persistentClass.getSimpleName() + " as model where 1=1 ");

        if (hqlWhere != null && hqlWhere.length() > 0) {
            queryString.append(hqlWhere);
        }

        int size = propertyNames.length;
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        queryString.append("" + orderByStuff);

        Query queryObject = entityManager.createQuery(queryString.toString());
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }
        return queryObject.getResultList();
    }

    @Override
    public int findByHqlWhereCount(String hqlWhere, String[] propertyNames, Object[] values) {
        if(propertyNames.length != values.length){
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append("select count(model) from " + persistentClass.getSimpleName() + " as model where 1=1 ");

        if (hqlWhere != null && hqlWhere.length() > 0) {
            queryString.append(hqlWhere);
        }

        int size = propertyNames.length;
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
            }
        }

        Query queryObject = entityManager.createQuery(queryString.toString());
        for (int i = 0; i < size; i++) {
            if(values[i] != null) {
                queryObject.setParameter(propertyNames[i], values[i]);
            }
        }

        try{
            Long count = entityManager.createQuery(queryString.toString(),Long.class).getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public List<T> findByHqlWherePage(String hqlWhere, Pager pager, String[] propertyNames, Object[] values, String orderByStuff) {
        if(pager != null){
            if(propertyNames.length != values.length){
                throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
            }
            StringBuffer queryString = new StringBuffer();
            queryString.append("from " + persistentClass.getSimpleName() + " as model where 1=1 ");

            if (hqlWhere != null && hqlWhere.length() > 0) {
                queryString.append(hqlWhere);
            }

            int size = propertyNames.length;
            for (int i = 0; i < size; i++) {
                if(values[i] != null) {
                    queryString.append(" and model." + propertyNames[i] + "= :" + propertyNames[i]);
                }
            }
            queryString.append(" " + orderByStuff);

            Query queryObject = entityManager.createQuery(queryString.toString()).setFirstResult(pager.getStartRow()).setMaxResults(pager.getPageSize());
            for (int i = 0; i < size; i++) {
                if(values[i] != null) {
                    queryObject.setParameter(propertyNames[i], values[i]);
                }
            }

            return queryObject.getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Deprecated
    @Override
    public List<T> findByHqlWherePage(String hqlWhere, Pager pager) {
        if(pager != null) {
            StringBuffer queryString = new StringBuffer();
            queryString.append("from " + persistentClass.getSimpleName() + " as model where 1=1 ");

            if (hqlWhere != null && hqlWhere.length() > 0) {
                queryString.append(hqlWhere);
            }

            return entityManager.createQuery(queryString.toString())
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Override
    public List<T> findByHqlWherePage(DdlPackBean packBean, Pager pager) {
        if(pager != null) {
            Query query = entityManager.createQuery("from " + persistentClass.getSimpleName()
                    + " as model where 1=1 " + packBean.getPackedHql());

            for (String key : packBean.getHqlPreparedMap().keySet()) {
                query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
            }

            return query.setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Deprecated
    @Override
    public int findByHqlWhereCount(String hqlWhere) {
        StringBuffer queryString = new StringBuffer();
        queryString.append("select count(model) from " + persistentClass.getSimpleName() + " as model where 1=1 ");

        if (hqlWhere != null && hqlWhere.length() > 0) {
            queryString.append(hqlWhere);
        }
        try{
            Long count = entityManager.createQuery(queryString.toString(), Long.class).getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public int findByHqlWhereCount(DdlPackBean packBean) {
        StringBuffer queryString = new StringBuffer();
        queryString.append("select count(model) from " + persistentClass.getSimpleName()
                + " as model where 1=1 " + packBean.getWhereAppend());

        Query query = entityManager.createQuery(queryString.toString(), Long.class);
        for (String key : packBean.getHqlPreparedMap().keySet()) {
            query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
        }
        try{
            Long count = (Long) query.getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public int findByHqlCount(String hql) {
        try{
            Long count = entityManager.createQuery(hql,Long.class).getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public int findByHqlCount(String hql, String[] paramName, Object[] paramValue) {
        Query queryObject = entityManager.createQuery(hql,Integer.class);
        for(int i=0;i<paramName.length;i++){
            if(paramValue[i] != null) {
                queryObject.setParameter(paramName[i], paramValue[i].toString());
            }
        }
        try{
            return (int) queryObject.getSingleResult();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public List<T> findByHqlPage(String hqlWhere, Pager pager) {
        if(pager != null){
            StringBuffer queryString = new StringBuffer();
            queryString.append("from " + persistentClass.getSimpleName() + " as model where 1=1 ");

            if (hqlWhere != null && hqlWhere.length() > 0) {
                queryString.append(hqlWhere);
            }

            return entityManager.createQuery(queryString.toString())
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Override
    public List<T> findByHqlPage(DdlPackBean packBean, Pager pager) {
        if(pager != null){
            Query query = entityManager.createQuery("from " + persistentClass.getSimpleName()
                    + " as model where 1=1 " + packBean.getPackedHql());

            for (String key : packBean.getHqlPreparedMap().keySet()) {
                query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
            }

            return query.setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Override
    public List<T> findByHqlPage(String hql, Pager pager, String[] paramName, Object[] paramValue) {
        if(pager != null) {
            Query queryObject = entityManager.createQuery(hql);
            for (int i = 0; i < paramName.length; i++) {
                if (paramValue[i] != null) {
                    queryObject.setParameter(paramName[i], paramValue[i].toString());
                }
            }

            return queryObject.setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Override
    public List findBySql(String sql) {
        return entityManager.createNativeQuery(sql).getResultList();
    }

    @Override
    public List<?> findBySql(String sql, Class entity) {
        return entityManager.createNativeQuery(sql,entity).getResultList();
    }

    @Override
    public List findBySqlPage(String sql, Pager pager) {
        if(pager != null) {
            return entityManager.createNativeQuery(sql)
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList();
        }
    }

    @Override
    public List<?> findBySqlPage(String sql, Class entity, Pager pager) {
        if(pager != null){
            return entityManager.createNativeQuery(sql,entity)
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList();
        }
    }

    @Override
    public int executeSql(String sql) {
        return entityManager.createNativeQuery(sql).executeUpdate();
    }

    @Override
    public int findBySqlCount(String sql) {
        try{
            Long count = (Long) entityManager
                    .createNativeQuery("select count(*) from ( " + sql + " ) as usertable",Long.class)
                    .getSingleResult();
            return count == null ? 0 : count.intValue();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public double findBySqlSumDouble(String sql, String columnName) {
        try{
            return (double) entityManager
                    .createNativeQuery("select sum(" + columnName + ") from ( " + sql + " ) as usertable",Double.class)
                    .getSingleResult();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public double findByHqlDouble(String hql) {
        try{
            Double result = entityManager.createQuery(hql,Double.class).getSingleResult();
            return result == null ? 0 : result;
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public double findByHqlDouble(DdlPackBean packBean) {
        try{
            Query query = entityManager.createQuery(packBean.getPackedHqlAll(),Double.class);

            for (String key : packBean.getHqlPreparedMap().keySet()) {
                query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
            }

            Double result = (Double) query.getSingleResult();
            return result == null ? 0 : result;
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public long findByHqlLong(String hql) {
        try{
            return entityManager.createQuery(hql,Long.class).getSingleResult();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public long findByHqlLong(DdlPackBean packBean) {
        try{
            Query query = entityManager.createQuery("from " + persistentClass.getSimpleName()
                    + " as model where 1=1 " + packBean.getPackedHql(),Long.class);

            for (String key : packBean.getHqlPreparedMap().keySet()) {
                query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
            }

            return (long) query.getSingleResult();
        }catch(NoResultException e){
            return 0;
        }
    }

    @Override
    public List<T> findByHqlTopWhere(String hqlWhere, int topNum) {
        StringBuffer queryString = new StringBuffer();
        queryString.append("from " + persistentClass.getSimpleName() + " as model where 1=1 ");

        if (hqlWhere != null && hqlWhere.length() > 0) {
            queryString.append(hqlWhere);
        }
        return entityManager.createQuery(queryString.toString()).setFirstResult(0).setMaxResults(topNum).getResultList();
    }

    @Override
    public List<T> findByHqlTopWhere(DdlPackBean packBean, int topNum) {
        Query query = entityManager.createQuery("from " + persistentClass.getSimpleName()
                + " as model where 1=1 " + packBean.getPackedHql());

        for (String key : packBean.getHqlPreparedMap().keySet()) {
            query.setParameter("m_" + key,packBean.getHqlPreparedMap().get(key));
        }
        return query.setFirstResult(0).setMaxResults(topNum).getResultList();
    }

    @Override
    public List<T> findColumnsByHql(String hql, String hqlWhere, String orderByStuff, Pager pager) {
        if(pager != null) {
            StringBuffer queryString = new StringBuffer();

            queryString.append(hql + " as model where 1=1 ");

            if (hqlWhere != null && hqlWhere.length() > 0) {
                queryString.append(hqlWhere);
            }

            queryString.append(" " + orderByStuff);

            return entityManager.createQuery(queryString.toString())
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<T>();
        }
    }

    @Override
    public List<Object[]> findByHqlObjects(String hql) {
        return entityManager.createQuery(hql).getResultList();
    }

    @Override
    public List<Object[]> findByHqlObjects(String hql, String[] paramName, Object[] paramValue) {
        Query queryObject = entityManager.createQuery(hql);
        for(int i=0;i<paramName.length;i++){
            if(paramValue[i] != null) {
                queryObject.setParameter(paramName[i], paramValue[i].toString());
            }
        }

        return queryObject.getResultList();
    }

    @Override
    public List<Object[]> findByHqlPageObjects(String hql, Pager pager) {
        if(pager != null){
            return entityManager.createQuery(hql).setFirstResult(pager.getStartRow()).setMaxResults(pager.getPageSize()).getResultList();
        }else{
            return new ArrayList<Object[]>();
        }
    }

    @Override
    public List<Object[]> findByHqlPageObjects(String hql, Pager pager, String[] paramName, Object[] paramValue) {
        if(pager != null) {
            Query queryObject = entityManager.createQuery(hql);
            for (int i = 0; i < paramName.length; i++) {
                if (paramValue[i] != null) {
                    queryObject.setParameter(paramName[i], paramValue[i].toString());
                }
            }

            return queryObject.setFirstResult(pager.getStartRow()).setMaxResults(pager.getPageSize()).getResultList();
        }else{
            return new ArrayList<Object[]>();
        }
    }

    @Override
    public List<Object[]> findBySqlObjList(String sql) {
        return entityManager.createNativeQuery(sql).getResultList();
    }

    @Override
    public List<Object[]> findBySqlObjListByPager(String sql, Pager pager) {
        if(pager != null){
            return entityManager.createNativeQuery(sql)
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        }else{
            return new ArrayList<Object[]>();
        }
    }

    /**
     * 保存对象
     * @param item 保存对象
     * @return
     */
    private T innerSave(T item, boolean initParam) {
        try {
            if(item == null) {
                return null;
            }
            Class<?> clazz = item.getClass();

            //获取主键
            Field idField = clazz.getField("id");
            if(idField == null){
                idField = clazz.getField("primaryKey");
            }
            if(idField == null){
                // 遍历所有属性，以@Id声明确认主键
                Field[] fields = clazz.getFields();
                for(Field f : fields){
                    if(f.getAnnotation(Id.class) != null){
                        idField = f;
                        break;
                    }
                }
            }

            if(idField != null){
                Class<?> type = idField.getType();
                Object val = idField.get(item);
                if(type == Long.class && (val == null || Long.parseLong(val.toString()) == 0)){
                    // long类型主键，以snowflake为主键
                    idField.set(item, snowflakeIdMaker.nextId());
                } else if(type == String.class && (val==null || "".equals(val))){
                    // String类型主键，以UUID为主键
                    idField.set(item, UUID.randomUUID().toString().replace("-", "").toLowerCase());
                }
            }

            //属性值过滤，避免null值
            if(initParam){
                for (Field checkField : clazz.getFields()) {
                    if (!Modifier.isFinal(checkField.getModifiers()) && checkField.get(item) == null) {
                        // 未赋值的属性，进行初始化赋值
                        fieldSetInitParam(item, checkField);
                    }
                }
                for (Field checkField : clazz.getDeclaredFields()) {
                    checkField.setAccessible(true);
                    if (!Modifier.isFinal(checkField.getModifiers()) && checkField.get(item) == null) {
                        // 未赋值的属性，进行初始化赋值
                        fieldSetInitParam(item, checkField);
                    }
                }
            }

            entityManager.merge(item);
            entityManager.flush();
            if(idField!=null){
                return item;
            }else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 对为赋值的属性进行赋值
     * @param field
     */
    private void fieldSetInitParam(T item,Field field) {
        try {
            if (field.getType() == String.class) {
                field.set(item, "");
            } else if (field.getType() == Byte.class || field.getType() == Character.class || field.getType() == Integer.class) {
                field.set(item, 0);
            } else if(field.getType() == Long.class){
                field.set(item, 0L);
            } else if(field.getType() == Float.class){
                field.set(item, 0.0f);
            } else if(field.getType() == Double.class){
                field.set(item, 0.0d);
            } else if(field.getType() == Boolean.class){
                field.set(item, false);
            }
        } catch (IllegalAccessException e) {
            LOGGER.error("自动赋值出错：{}", e.getMessage(), e);
        }
    }

    /************** 部分业务 *************/
    private String getNowTime(boolean needSecond) {
        return needSecond ? getNowTime("yyyy-MM-dd HH:mm:ss") : getNowTime("yyyy-MM-dd HH:mm");
    }

    private String getNowTime(String format) {
        String dateTime;
        try {
            dateTime = (new SimpleDateFormat(format)).format(new Date());
        } catch (Exception e) {
            dateTime = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date());
        }

        return dateTime;
    }

    @Override
    public int deleteWeaklyById(ID id,String username) {
        return deleteWeaklyByProperty("id", id,username);
    }

    @Override
    public int deleteWeaklyByIds(Long[] ids,String username) {
        return deleteWeaklyByPropertyIn("id",  ids,username);
    }

    @Override
    public int deleteWeaklyByProperty(String propName, Object propValue,String username) {
        return deleteWeaklyByProperties(new String[] { propName }, new Object[] { propValue },username);
    }

    /**
     * 批量弱删除
     * @return
     */
    @Override
    public int deleteWeaklyByPropertyIn(String propName, Object[] propValues,String username) {
        if(propValues != null && propValues.length > 0){
            String hql = "update " + persistentClass.getName()
                    + " model set model.isDeleted =:modelIsDeleted,model.modifyUser=:modelModifyUser,model.modifyDatetime=:modelModifyDatetime  where model."
                    + propName + " in(:"+propName+") ";
            Query query = entityManager.createQuery(hql);
            query.setParameter("modelIsDeleted",CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            query.setParameter("modelModifyUser",username);
            query.setParameter("modelModifyDatetime",getNowTime(true));
            query.setParameter(propName, Arrays.asList(propValues));

            return query.executeUpdate();
        }else{
            throw new IllegalArgumentException("弱删除失败："+propName+":" + propValues);
        }
    }

    /**
     * 批量弱删除
     * @return
     */
    @Override
    public int deleteWeaklyByProperties(String[] propName, Object[] propValue,String username) {
        if ((propName != null) && (propName.length > 0) && (propValue != null) && (propValue.length > 0) && (propValue.length == propName.length)) {
            StringBuffer sb = new StringBuffer("update " + persistentClass.getName()
                    + " model set model.isDeleted = :modelDeleted,model.modifyUser= :modelModifyUser,model.modifyDatetime=:modelModifyDatetime where 1=1 ");
            appendQL(sb,propName,propValue);
            Query query = entityManager.createQuery(sb.toString());
            query.setParameter("modelModifyUser",username);
            query.setParameter("modelModifyDatetime",getNowTime(true));
            query.setParameter("modelDeleted",CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());

            setParameter(query,propName,propValue);

            return query.executeUpdate();
        }else{
            throw new IllegalArgumentException("弱删除失败："+propName+":" + propValue);
        }
    }

    @Override
    public int updateValidStatusById(ID id,int status,String username) {
        return updateValidStatusByProperty("id", id,status,username);
    }

    @Override
    public int updateValidStatusByIds(Long[] ids,int status,String username) {
        return updateValidStatusByPropertyIn("id",  ids,status,username);
    }

    @Override
    public int updateValidStatusByProperty(String propName, Object propValue,int status,String username) {
        return updateValidStatusByProperties(new String[] { propName }, new Object[] { propValue },status,username);
    }

    /**
     * 批量禁用
     * @return
     */
    @Override
    public int updateValidStatusByPropertyIn(String propName, Object[] propValues,int status,String username) {
        if(propValues != null && propValues.length > 0){
            String hql = "update " + persistentClass.getName()
                    + " model set model.isValid =:modelIsValid ,model.modifyUser=:modelModifyUser,model.modifyDatetime=:modelModifyDatetime where model."
                    + propName + " in(:"+propName+") ";
            Query query = entityManager.createQuery(hql);
            query.setParameter("modelModifyUser",username);
            query.setParameter("modelModifyDatetime",getNowTime(true));
            query.setParameter("modelIsValid",status);
            query.setParameter(propName, Arrays.asList(propValues));

            return query.executeUpdate();
        }else{
            throw new IllegalArgumentException("修改状态失败："+propName+":" + propValues);
        }
    }

    /**
     * 批量禁用
     * @return
     */
    @Override
    public int updateValidStatusByProperties(String[] propName, Object[] propValue,int status,String username) {
        if ((propName != null) && (propName.length > 0) && (propValue != null) && (propValue.length > 0) && (propValue.length == propName.length)) {
            StringBuffer sb = new StringBuffer("update " + persistentClass.getName()
                    + " model set model.isValid = :modelIsValid,model.modifyUser= :modelModifyUser,model.modifyDatetime=:modelModifyDatetime where 1=1 ");
            appendQL(sb,propName,propValue);
            Query query = entityManager.createQuery(sb.toString());
            query.setParameter("modelModifyUser",username);
            query.setParameter("modelModifyDatetime",getNowTime(true));
            query.setParameter("modelIsValid",status);

            setParameter(query,propName,propValue);

            return query.executeUpdate();
        }else{
            throw new IllegalArgumentException("修改状态失败："+propName+":" + propValue);
        }
    }

    @Override
    public boolean isExitByProperty(String propertyName, Object value) {
        //大于0，存在
        return findByPropertyCount(propertyName,value) > 0;
    }

    @Override
    public boolean isExitByProperty(String[] propertyNames, Object[] values) {
        return findByPropertyCount(propertyNames, values) > 0;
    }

    @Override
    public boolean isExitByPropertyDemo(String[] propertyNames, Object[] values) {
        return findByPropertyCountDemo(propertyNames, values) > 0;
    }

    @Override
    public boolean isExitByHqlWhere(String hqlWhere, String[] propertyNames, Object[] values) {
        return findByHqlWhereCount(hqlWhere,propertyNames,values) > 0;
    }

    @Override
    public boolean isExitByHqlWhere(String hqlWhere) {
        return findByHqlWhereCount(hqlWhere) > 0;
    }

    @Override
    public boolean isExitByHql(String hql) {
        return findByHqlCount(hql) > 0;
    }

    @Override
    public boolean isExitByHql(DdlPackBean packBean) {
        return findByHqlWhereCount(packBean) > 0;
    }

    @Override
    public boolean isExitByHql(String hql, String[] paramName, Object[] paramValue) {
        return findByHqlCount(hql) > 0;
    }

    @Override
    public boolean isExitBySql(String sql) {
        return findBySqlCount(sql) > 0;
    }

    @Override
    public double findSumByProperty(String sumPropertyName, String groupByName, String propertyName, Object value) {
        return findSumByProperties(sumPropertyName,groupByName,new String[]{propertyName},new Object[]{value});
    }

    @Override
    public double findSumByProperties(String sumPropertyName, String groupByName, String[] paramName, Object[] paramValue) {
        if ((paramName != null) && (paramName.length > 0) && (paramValue != null) && (paramValue.length > 0)) {
            StringBuffer sb = new StringBuffer("select sum(model." + sumPropertyName + ") from " + persistentClass.getName() + " model where 1=1 ");
            appendQL(sb, paramName, paramValue);

            if(StringUtils.isNotBlank(groupByName)) {
                sb.append(" group by model." + groupByName);
            }

            Query query = entityManager.createQuery(sb.toString());
            setParameter(query,paramName,paramValue);

            return getNumberByResultList(query.getResultList());
        }else{
            throw new IllegalArgumentException("sum查询错误!paramName:" + paramName + ",paramValue:" + paramValue);
        }
    }

    @Override
    public double findAvgByProperty(String sumPropertyName, String groupByName, String propertyName, Object value) {
        return findAvgByProperties(sumPropertyName,groupByName,new String[]{propertyName},new Object[]{value});
    }

    @Override
    public double findAvgByProperties(String sumPropertyName, String groupByName, String[] paramName, Object[] paramValue) {
        if ((paramName != null) && (paramName.length > 0) && (paramValue != null) && (paramValue.length > 0)) {
            StringBuffer sb = new StringBuffer("select avg(model."+sumPropertyName+") from " + persistentClass.getName() + " model where 1=1 ");
            appendQL(sb,paramName,paramValue);

            if(StringUtils.isNotBlank(groupByName)) {
                sb.append(" group by model." + groupByName);
            }

            Query query = entityManager.createQuery(sb.toString());
            setParameter(query,paramName,paramValue);

            return getNumberByResultList(query.getResultList());
        }else{
            throw new IllegalArgumentException("sum查询错误!paramName:" + paramName + ",paramValue:" + paramValue);
        }
    }

    @Override
    public double findMaxByProperty(String sumPropertyName, String groupByName, String propertyName, Object value) {
        return findMaxByProperties(sumPropertyName,groupByName,new String[]{propertyName},new Object[]{value});
    }

    @Override
    public double findMaxByProperties(String sumPropertyName, String groupByName, String[] paramName, Object[] paramValue) {
        if ((paramName != null) && (paramName.length > 0) && (paramValue != null) && (paramValue.length > 0)) {
            StringBuffer sb = new StringBuffer("select max(CAST(model." + sumPropertyName + " as integer)) from " + persistentClass.getName() + " model where 1=1 ");
            appendQL(sb, paramName, paramValue);
            if(StringUtils.isNotBlank(groupByName)){
                sb.append(" group by model." + groupByName);
            }

            Query query = entityManager.createQuery(sb.toString());
            setParameter(query,paramName,paramValue);

            return getNumberByResultList(query.getResultList());
        }else{
            throw new IllegalArgumentException("sum查询错误!paramName:" + paramName + ",paramValue:" + paramValue);
        }
    }

    @Override
    public double findMinByProperty(String sumPropertyName, String groupByName, String propertyName, Object value) {
        return findMinByProperties(sumPropertyName,groupByName,new String[]{propertyName},new Object[]{value});
    }

    @Override
    public double findMinByProperties(String sumPropertyName, String groupByName, String[] paramName, Object[] paramValue) {
        if ((paramName != null) && (paramName.length > 0) && (paramValue != null) && (paramValue.length > 0)) {
            StringBuffer sb = new StringBuffer("select min(model." + sumPropertyName + ") from " + persistentClass.getName() + " model where 1=1 ");
            appendQL(sb, paramName, paramValue);

            if(StringUtils.isNotBlank(groupByName)) {
                sb.append(" group by model." + groupByName);
            }

            Query query = entityManager.createQuery(sb.toString());
            setParameter(query,paramName,paramValue);

            return getNumberByResultList(query.getResultList());
        }else{
            throw new IllegalArgumentException("sum查询错误!paramName:" + paramName + ",paramValue:" + paramValue);
        }
    }

    //从结果集中获取数字转换
    public double getNumberByResultList(List objList){
        double num = 0.0;
        if(objList != null && objList.size() > 0){
            if(objList.get(0) != null){
                try {
                    num = Double.parseDouble(objList.get(0).toString());
                }catch(NumberFormatException ne){
                    LOGGER.error("数字转换出错!",ne);
                }
            }
        }
        return num;
    }

    @Override
    public List<T> findByHqlWhereByClear(DdlPackBean packBean, String dateTime) {
        LOGGER.info("PTL-PCN数据清除查询");
        StringBuffer queryString = new StringBuffer();
        queryString.append("select model from " + persistentClass.getSimpleName()
                + " as model where 1=1 and model.modifyDatetime < " + "'" + dateTime + "'" + " ");

        if (packBean != null) {
            queryString.append(packBean.getWhereAppend());
        }

        Query query = entityManager.createQuery(queryString.toString());
        if (packBean != null) {
            for (String key : packBean.getHqlPreparedMap().keySet()) {
                query.setParameter("m_" + key, packBean.getHqlPreparedMap().get(key));
            }
        }

        return query.getResultList();
    }
}
