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

import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.enumutil.MdmEnumUtil;
import cn.estsh.i3plus.pojo.mdm.bean.base.BaseMdmBean;
import cn.estsh.i3plus.pojo.mdm.bean.base.BaseMdmBusiExtdBean;
import cn.estsh.i3plus.pojo.mdm.bean.base.BaseMdmBusiModelBean;
import cn.estsh.i3plus.pojo.mdm.bean.base.DdlPackMdmModelBean;
import cn.estsh.i3plus.pojo.mdm.jpa.dao.MdmBusiModelRepository;
import org.hibernate.NonUniqueResultException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import java.lang.reflect.ParameterizedType;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @Description : 自定义持久化接口实现
 * @Reference :
 * @Author : yunhao
 * @CreateDate : 2020-05-21 15:05
 * @Modify:
 **/
public class MdmBusiModelRepositoryImpl<T extends BaseMdmBusiModelBean<M, B>, M extends BaseMdmBean, B extends BaseMdmBusiExtdBean>
        implements MdmBusiModelRepository<T, M, B> {
    public static final Logger LOGGER = LoggerFactory.getLogger(MdmBusiModelRepositoryImpl.class);

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

    private final Class<T> modelClass;
    private final Class<M> masterClass;
    private final Class<B> busiExtdClass;

    private final String selectCount;
    private final String selectAll;
    private final String formStr;

    public MdmBusiModelRepositoryImpl() {
        // 通过反射获取model的真实类型
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        modelClass = (Class<T>) pt.getActualTypeArguments()[0];
        masterClass = (Class<M>) pt.getActualTypeArguments()[1];
        busiExtdClass = (Class<B>) pt.getActualTypeArguments()[2];

        this.formStr = String.format("from %s as busi left join %s as master on busi.mdmMasterId = master.id ",
                busiExtdClass.getName(), masterClass.getName()
        );

        this.selectCount = "select count(distinct busi) " + formStr;
        this.selectAll = MessageFormat.format("select new {0}(master,busi) ", modelClass.getName()) + formStr;
    }

    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 getById(long id) {
        try {
            List<T> busiModelList =
                    entityManager.createQuery(selectAll + " where busi.id = :busi_id").setParameter("busi_id", id).getResultList();

            return busiModelList.isEmpty() ? modelClass.newInstance() : busiModelList.get(0);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<T> list() {
        List<T> l = entityManager.createQuery(selectAll).getResultList();
        return l;
    }

    @Override
    public List<T> listPager(Pager pager) {
        if (pager.getTotalRows() > 0) {
            return entityManager.createQuery(selectAll)
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        } else {
            return new ArrayList<>();
        }
    }

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

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

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

        for (int i = 0; i < packBean.getKeyList().size(); i++) {
            query.setParameter(
                    packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                    packBean.getValueList().get(i)
            );
        }

        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(MdmEnumUtil.HQL_ENTITY_TYPE entityType, String propertyName, Object value) {
        String queryString = MessageFormat.format("{0}  where {1}.{2}= :{3}_{4}", selectAll, entityType.getAlias(), propertyName,
                entityType.getAlias(), propertyName);
        return entityManager.createQuery(queryString).setParameter(entityType.getAlias() + "_" + propertyName, value).getResultList();
    }

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

        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(
                        MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                        )
                );
            }
        }

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

        return queryObject.getResultList();
    }

    @Override
    public List<T> findByProperty(MdmEnumUtil.HQL_ENTITY_TYPE entityType, String propertyName, Object value, String orderByStuff) {
        String queryString = MessageFormat.format("{0} where {1}.{2}= :{3} {4}", selectAll, entityType.getAlias(), propertyName, propertyName, orderByStuff);
        return entityManager.createQuery(queryString).setParameter(propertyName, value).getResultList();
    }

    @Override
    public List<T> findByProperty(MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, 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(selectAll);

        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(
                        MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                        )
                );
            }
        }

        queryString.append(" " + orderByStuff);

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

        return queryObject.getResultList();
    }

    @Override
    public T getByProperty(DdlPackMdmModelBean packBean) {

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

    @Override
    public T getByProperty(MdmEnumUtil.HQL_ENTITY_TYPE entityType, String propertyName, Object value) {
        String queryString =
                selectAll + " where " + entityType.getAlias() + "." + propertyName + "= :" + entityType.getAlias() + "_" + propertyName;
        try {
            List<T> list = entityManager.createQuery(queryString)
                    .setParameter(entityType.getAlias() + "_" + propertyName, value)
                    .getResultList();
            return list.size() != 0 ? list.get(0) : null;
        } catch (NoResultException ne) {
            LOGGER.error("数据不存在，prop：{},value：{}", propertyName, value, ne);
            return null;
        } catch (NonUniqueResultException ex) {
            LOGGER.error("查询单条记录，但出现多条。prop：{},value：{}", propertyName, value, ex);
            throw new RuntimeException("存在多条记录：" + ex.getMessage());
        }
    }

    @Override
    public T getByProperty(MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, String[] propertyNames, Object[] values) {
        if (propertyNames.length != values.length) {
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append(selectAll);

        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(
                        MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                        )
                );
            }
        }

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

        try {
            List<T> list = queryObject.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(selectCount, Long.class).getSingleResult();
            return count == null ? 0 : count.intValue();
        } catch (NoResultException e) {
            return 0;
        }
    }

    @Override
    public int findByPropertyCount(MdmEnumUtil.HQL_ENTITY_TYPE entityType, String propertyName, Object value) {
        try {
            String queryString = selectCount + " where " + entityType.getAlias() + "." + propertyName
                    + "= :" + entityType.getAlias() + "_" + propertyName;
            Long count = entityManager.createQuery(queryString, Long.class)
                    .setParameter(entityType.getAlias() + "_" + propertyName, value)
                    .getSingleResult();
            return count == null ? 0 : count.intValue();
        } catch (NoResultException e) {
            return 0;
        }
    }

    @Override
    public int findByPropertyCount(MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, 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(distinct model) from " + masterClass.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(
                        MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                                , entityTypes[i].getAlias()
                                , 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;
        }
    }

    @Override
    public List<T> findByPropertyPage(MdmEnumUtil.HQL_ENTITY_TYPE entityType, String propertyName, Object value, String orderByStuff, Pager pager) {
        if (pager.getTotalRows() > 0) {
            String queryString = selectAll + "  where " + entityType.getAlias() + "." + propertyName + "= :" + entityType.getAlias() + "_" + propertyName + " " + orderByStuff;
            return entityManager.createQuery(queryString)
                    .setParameter(entityType.getAlias() + "_" + propertyName, value)
                    .getResultList();
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public List<T> findByPropertyPage(MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, String[] propertyNames, Object[] values,
                                      String orderByStuff, Pager pager) {
        if (pager.getTotalRows() > 0) {
            if (propertyNames.length != values.length) {
                throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
            }
            StringBuffer queryString = new StringBuffer();
            queryString.append(selectAll);

            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(
                            MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                    , entityTypes[i].getAlias()
                                    , propertyNames[i]
                                    , entityTypes[i].getAlias()
                                    , 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(entityTypes[i].getAlias() + "_" + propertyNames[i], values[i]);
            }

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

    @Override
    public List<T> findByHqlWhere(DdlPackMdmModelBean packBean) {
        Query query = entityManager.createQuery(selectAll + " where 1=1 " + packBean.getPackedHql());

        for (int i = 0; i < packBean.getKeyList().size(); i++) {
            query.setParameter(
                    packBean.getEntityTypeList().get(i).getAlias() + "_" + packBean.getKeyList().get(i),
                    packBean.getValueList().get(i)
            );
        }
        return query.getResultList();
    }

    @Override
    public List<T> findByHqlWhere(String hqlWhere, MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, 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(selectAll + " as  where 1=1 ");

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

        int size = propertyNames.length;
        for (int i = 0; i < size; i++) {
            if (propertyNames[i] != null) {
                queryString.append(
                        MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                        )
                );
            }
        }

        queryString.append("" + orderByStuff);

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

    @Override
    public int findByHqlWhereCount(String hqlWhere, MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, String[] propertyNames, Object[] values) {
        if (propertyNames.length != values.length) {
            throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
        }
        StringBuffer queryString = new StringBuffer();
        queryString.append(selectCount + " 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(
                        MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                                , entityTypes[i].getAlias()
                                , propertyNames[i]
                        )
                );
            }
        }

        Query queryObject = entityManager.createQuery(queryString.toString());
        for (int i = 0; i < size; i++) {
            if (values[i] != null) {
                queryObject.setParameter(entityTypes[i].getAlias() + "_" + 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, MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, String[] propertyNames, Object[] values, String orderByStuff) {
        if (pager.getTotalRows() > 0) {
            if (propertyNames.length != values.length) {
                throw new IllegalArgumentException("参数名的数量和参数值不匹配!propertyNames:" + propertyNames.length + ",values:" + values.length);
            }
            StringBuffer queryString = new StringBuffer();
            queryString.append(selectAll + " 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(
                            MessageFormat.format(" and {0}.{1}= :{2}_{3}"
                                    , entityTypes[i].getAlias()
                                    , propertyNames[i]
                                    , entityTypes[i].getAlias()
                                    , 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(entityTypes[i].getAlias() + "_" + propertyNames[i], values[i]);
                }
            }

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

    @Override
    public List<T> findByHqlWherePage(DdlPackMdmModelBean packBean, Pager pager) {
        if (pager.getTotalRows() > 0) {
            Query query = entityManager.createQuery(selectAll + " where 1=1 " + packBean.getPackedHql());

            for (int i = 0; i < packBean.getKeyList().size(); i++) {
                query.setParameter(
                        packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                        packBean.getValueList().get(i)
                );
            }

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

    @Override
    public int findByHqlWhereCount(DdlPackMdmModelBean packBean) {
        StringBuffer queryString = new StringBuffer();
        queryString.append(selectCount + " where 1=1 " + packBean.getWhereAppend());

        Query query = entityManager.createQuery(queryString.toString(), Long.class);
        for (int i = 0; i < packBean.getKeyList().size(); i++) {
            query.setParameter(
                    packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                    packBean.getValueList().get(i)
            );
        }
        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, MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, 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(entityTypes[i].getAlias() + "_" + paramName[i], paramValue[i]);
            }
        }
        try {
            return (int) queryObject.getSingleResult();
        } catch (NoResultException e) {
            return 0;
        }
    }

    @Override
    public List<T> findByHqlPage(DdlPackMdmModelBean packBean, Pager pager) {
        if (pager.getTotalRows() > 0) {
            Query query = entityManager.createQuery(selectAll + " where 1=1 " + packBean.getPackedHql());

            for (int i = 0; i < packBean.getKeyList().size(); i++) {
                query.setParameter(
                        packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                        packBean.getValueList().get(i)
                );
            }

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

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

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

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

            for (int i = 0; i < packBean.getKeyList().size(); i++) {
                query.setParameter(
                        packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                        packBean.getValueList().get(i)
                );
            }

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

    @Override
    public long findByHqlLong(DdlPackMdmModelBean packBean) {
        try {
            Query query = entityManager.createQuery(selectAll + " where 1=1 " + packBean.getPackedHql(), Long.class);

            for (int i = 0; i < packBean.getKeyList().size(); i++) {
                query.setParameter(
                        packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                        packBean.getValueList().get(i)
                );
            }

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

    @Override
    public List<T> findByHqlTopWhere(DdlPackMdmModelBean packBean, int topNum) {
        Query query = entityManager.createQuery(selectAll + " where 1=1 " + packBean.getPackedHql());

        for (int i = 0; i < packBean.getKeyList().size(); i++) {
            query.setParameter(
                    packBean.getEntityTypeList().get(i).getAlias() + "." + packBean.getKeyList().get(i),
                    packBean.getValueList().get(i)
            );
        }

        return query.setFirstResult(0).setMaxResults(topNum).getResultList();
    }

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

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

        return queryObject.getResultList();
    }

    @Override
    public List<Object[]> findByHqlPageObjects(String hql, Pager pager) {
        if (pager.getTotalRows() > 0) {
            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, MdmEnumUtil.HQL_ENTITY_TYPE[] entityTypes, String[] propertyNames, Object[] values) {
        if (pager.getTotalRows() > 0) {
            Query queryObject = entityManager.createQuery(hql);
            for (int i = 0; i < propertyNames.length; i++) {
                if (propertyNames[i] != null) {
                    queryObject.setParameter(entityTypes[i].getAlias() + "_" + propertyNames[i], values[i]);
                }
            }

            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.getTotalRows() > 0) {
            return entityManager.createNativeQuery(sql)
                    .setFirstResult(pager.getStartRow())
                    .setMaxResults(pager.getPageSize())
                    .getResultList();
        } else {
            return new ArrayList<Object[]>();
        }
    }

    /************** 部分业务 *************/
    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 boolean isExitByProperty(MdmEnumUtil.HQL_ENTITY_TYPE entityType, String propertyName, Object value) {
        //大于0，存在
        return findByPropertyCount(entityType, propertyName, value) > 0;
    }

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

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

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


}
