/**************************************************************************************** 
 Copyright © 2003-2012 hbasesoft Corporation. All rights reserved. Reproduction or       <br>
 transmission in whole or in part, in any form or by any means, electronic, mechanical <br>
 or otherwise, is prohibited without the prior written consent of the copyright owner. <br>
 ****************************************************************************************/
package com.hbasesoft.framework.db.jdbc;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.PreparedStatement;
import java.sql.SQLException;



import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Objects;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.ArrayList;
import java.util.stream.Collectors;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.persistence.Id;
import javax.sql.DataSource;

import com.hbasesoft.framework.common.GlobalConstants;
import com.hbasesoft.framework.db.core.BaseEntity;
import com.hbasesoft.framework.db.core.criteria.AbstractQueryWrapper;
import com.hbasesoft.framework.db.core.criteria.AbstractWrapper;
import com.hbasesoft.framework.db.core.criteria.DeleteWrapper;
import com.hbasesoft.framework.db.core.criteria.LambdaQueryWrapper;
import com.hbasesoft.framework.db.core.criteria.QueryWrapper;
import com.hbasesoft.framework.db.core.criteria.LambdaUpdateWrapper;
import com.hbasesoft.framework.db.core.criteria.UpdateWrapper;
import com.hbasesoft.framework.db.core.criteria.TempPredicate;
import com.hbasesoft.framework.db.core.criteria.LambdaDeleteWrapper;
import com.hbasesoft.framework.db.core.criteria.TempSelection;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;

import com.hbasesoft.framework.common.ErrorCodeDef;
import com.hbasesoft.framework.common.utils.Assert;
import com.hbasesoft.framework.common.utils.logger.Logger;
import com.hbasesoft.framework.db.core.DaoConstants;
import com.hbasesoft.framework.db.core.DaoException;
import com.hbasesoft.framework.db.core.DynamicDataSourceManager;
import com.hbasesoft.framework.db.core.config.DaoTypeDef;
import com.hbasesoft.framework.db.core.config.DataParam;
import com.hbasesoft.framework.db.core.utils.PagerList;
import com.hbasesoft.framework.db.core.utils.SQlCheckUtil;
import com.hbasesoft.framework.db.orm.util.DataSourceUtil;

/**
 * <Description> <br>
 * 
 * @author 王伟<br>
 * @version 1.0<br>
 * @taskId <br>
 * @since V1.0<br>
 * @param <T>
 * @CreateDate Feb 26, 2022 <br>
 * @since V1.0<br>
 * @see com.hbasesoft.framework.db.jdbc <br>
 */

public class BaseJdbcDao<T extends BaseEntity> implements IBaseDao4Jdbc<T> {
    /**
     *
     */
    private static final int INT = 10;

    /**
     *
     */
    private static final int INT1 = 1000;

    /**
     *  定义一个静态的不可变集合，包含所有标量类型
     */
    private static final List<Class<?>> SCALAR_TYPES = Arrays.asList(
            Integer.class, int.class,
            Long.class, long.class,
            Double.class, double.class,
            Float.class, float.class,
            Short.class, short.class,
            Byte.class, byte.class,
            Boolean.class, boolean.class,
            String.class,
            BigInteger.class,
            BigDecimal.class
    );

    /**
     *
     */
    private static final int PAGE_SIZE = 10;

    /**
     * logger
     */
    private static Logger logger = new Logger(BaseJdbcDao.class);

    /**
     * entity class
     */
    private Class<?> entityClazz;

    /**
     *
     */
    private static Map<String, NamedParameterJdbcTemplate> jdbcTemplate = new HashMap<>();

    /**
     * Description: <br>
     *
     * @param sql
     * @param param
     * @return
     * @throws DaoException <br>
     * @author 王伟<br>
     * @taskId <br>
     */
    @SuppressWarnings({
            "unchecked", "rawtypes"
    })
    @Override
    public Object query(final String sql, final DataParam param) throws DaoException {
        try {
            SQlCheckUtil.checkSql(sql);

            // Redis缓存序列化时不能有void返回类型，特殊处理一下
            if (param.getReturnType() == null) { // @sql返回值类型
                param.setReturnType(void.class);
            }

            Map<String, Object> dataMap = param.getParamMap();

            String lowerCaseSql = sql.toLowerCase();

            RowMapper<?> rowMap = null;
            // step2:设置返回值类型
            final Object callBack = param.getCallback(); // 自定义映射
            if (callBack != null && callBack instanceof RowMapper) {
                RowMapper rm = (RowMapper) callBack;
                rowMap = rm;
            }
            else if (param.getBeanType().equals(Map.class)) { //返回值类型的具体bean
                rowMap = new ColumnMapRowMapper();
            }
            else {
                Class<?> beanType = param.getBeanType();
                if (SCALAR_TYPES.contains(beanType)) {
                    // 处理标量查询
                    return getJdbcTemplate().queryForObject(sql, dataMap, beanType);
                }
                else if (Serializable.class.equals(beanType)) {
                    beanType = param.getReturnType();
                    if (entityClazz != null && List.class.isAssignableFrom(param.getReturnType())) {
                        beanType = entityClazz;
                    }
                }
                rowMap = new BeanPropertyRowMapper(beanType);
            }

            // 处理分页
            if (dataMap.containsKey(DaoConstants.PAGE_INDEX)) {
                int pageIndex = Integer.parseInt(dataMap.get(DaoConstants.PAGE_INDEX).toString());
                if (pageIndex <= 0) {
                    pageIndex = 1;
                }

                int pageSize = dataMap.containsKey(DaoConstants.PAGE_SIZE)
                        ? Integer.parseInt(dataMap.get(DaoConstants.PAGE_SIZE).toString())
                        : INT;
                if (pageSize <= 0 || pageSize > INT1) {
                    pageSize = PAGE_SIZE;
                }

                int orderByIndex = lowerCaseSql.lastIndexOf(" order by ");

                StringBuilder pageScript = new StringBuilder().append("SELECT COUNT(1) FROM (")
                        .append(orderByIndex != -1 ? sql.substring(0, orderByIndex) : sql).append(") QUERY_DATA__");
                long total = getJdbcTemplate().queryForObject(pageScript.toString(), dataMap, Long.class);

                PagerList list = new PagerList();
                list.setPageIndex(pageIndex);
                list.setPageSize(pageSize);
                list.setTotalCount(total);

                if (total > 0 && (pageIndex - 1) * pageSize < total) {
                    List<?> datas = getJdbcTemplate().query(new StringBuilder().append(sql).append(" limit ")
                        .append((pageIndex - 1) * pageSize).append(',').append(pageSize).toString(), dataMap, rowMap);
                    list.addAll(datas);
                }
                return list;
            }
            return getJdbcTemplate().query(sql, dataMap, rowMap);
        }
        catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new DaoException(ErrorCodeDef.QUERY_ERROR, e);
        }
    }

    /**
     * Description: <br>
     *
     * @param sql
     * @param param
     * @return
     * @throws DaoException <br>
     * @author 王伟<br>
     * @taskId <br>
     */
    @Override
    public int excuteSql(final String sql, final DataParam param) throws DaoException {
        try {
            SQlCheckUtil.checkSql(sql);
            return getJdbcTemplate().update(sql, param.getParamMap());
        }
        catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new DaoException(ErrorCodeDef.EXECUTE_ERROR, e);
        }
    }

    /**
     * Description: <br>
     *
     * @param sqls
     * @param param
     * @return
     * @throws DaoException <br>
     * @author 王伟<br>
     * @taskId <br>
     */
    @Override
    public int[] batchExcuteSql(final String[] sqls, final DataParam param) throws DaoException {
        try {

            int[] result = new int[sqls.length];
            NamedParameterJdbcTemplate template = getJdbcTemplate();
            for (int i = 0; i < sqls.length; i++) {
                String sql = sqls[i];
                SQlCheckUtil.checkSql(sql);
                result[i] = template.update(sql, param.getParamMap());
            }
            return result;
        }
        catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new DaoException(ErrorCodeDef.BATCH_EXECUTE_ERROR, e);
        }
    }

    /**
     * Description: <br>
     *
     * @param sql
     * @param objcts
     * @param commitNumber
     * @return int[]
     * @author 王伟<br>
     * @taskId <br>
     */
    @Override
    public int[] batchExecute(final String sql, final Collection<T> objcts, final int commitNumber) {
        if (CollectionUtils.isEmpty(objcts)) {
            return new int[0];
        }

        SqlParameterSource[] datas = SqlParameterSourceUtils.createBatch(objcts);
        ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
        SqlParameterSource paramSource = datas[0];

        String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
        List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
        PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);

        return getJdbcTemplate().getJdbcOperations().batchUpdate(pscf.getSql(), new BatchPreparedStatementSetter() {
            @Override
            public void setValues(final PreparedStatement ps, final int i) throws SQLException {
                Object[] values = NamedParameterUtils.buildValueArray(parsedSql, datas[i], null);
                pscf.newPreparedStatementSetter(values).setValues(ps);
            }

            @Override
            public int getBatchSize() {
                return commitNumber;
            }
        });

    }

    @Override
    public int updateBySql(final String sql) throws DaoException {
        DataParam param = new DataParam();
        param.setParamMap(new HashMap<String, Object>());
        int excuted = excuteSql(sql, param);
        return excuted;
    }

    /**
     * Description: <br>
     *
     * @param entityClazz <br>
     * @author 王伟<br>
     * @taskId <br>
     */
    public void setEntityClazz(final Class<?> entityClazz) {
        this.entityClazz = entityClazz;
    }

    private NamedParameterJdbcTemplate getJdbcTemplate() {
        synchronized (jdbcTemplate) {
            String code = DynamicDataSourceManager.getInstance(DaoTypeDef.db).getDataSourceCode();
            NamedParameterJdbcTemplate template = jdbcTemplate.get(code);
            if (template == null) {
                DataSource dataSource = DataSourceUtil.getDataSource(code);
                Assert.notNull(dataSource, ErrorCodeDef.DB_DATASOURCE_NOT_SET, code);
                template = new NamedParameterJdbcTemplate(dataSource);
            }
            return template;
        }
    }


    @Override
    public void delete(final DeleteSpecification<T> specification) {
        deleteBySpecification(specification.toSpecification(new DeleteWrapper<>()));
    }

    private void deleteBySpecification(final AbstractWrapper<?> wrapper) {
        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }
        Map<String, Object> parseEntityNameMap = parseEntityName(entityClazz, true);
        StringBuilder sqlBuilder = new StringBuilder().append("DELETE FROM ").append(getTableName(entityClazz));
        DataParam param = new DataParam();
        toPredicate(wrapper, parseEntityNameMap, sqlBuilder, param);
        // 如果没有条件直接抛出异常
        Assert.notEmpty(param.getParamMap(), ErrorCodeDef.PARAM_NOT_NULL, "删除的条件");
        //执行 sql
        excuteSql(sqlBuilder.toString(), param);
    }

    @Override
    public void delete(final T entity) {
        // 解析实体类并获取表结构信息
        Map<String, Object> columnValues = parseEntity(entity, true);
        if (MapUtils.isEmpty(columnValues)) {
            throw new DaoException(ErrorCodeDef.ANALYSIS_ENTITY_ERROR);
        }

        DataParam param = new DataParam();
        param.setParamMap(columnValues);

        // 使用 StringBuilder 构建 DELETE SQL 语句
        StringBuilder sqlBuilder = new StringBuilder("DELETE FROM ");
        sqlBuilder.append(getTableName(entity.getClass())).append(" WHERE ");
        StringBuilder whereClause = new StringBuilder();
        for (String col : columnValues.keySet()) {
            // 跳过主键字段，因为它不是要更新的数据部分
            if (StringUtils.equals("ENTITY_ID", col)) {
                continue;
            }
            if (whereClause.length() > 0) {
                whereClause.append(" AND ");
            }
            whereClause.append(col).append(" = :").append(col); // 使用命名参数
        }
        sqlBuilder.append(whereClause);

        // 执行 SQL 语句
        excuteSql(sqlBuilder.toString(), param);
    }

    @Override
    public void deleteBatch(final Collection<T> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return;
        }
        //获取主键
        Field primaryKeyField = findPrimaryKeyField(entities.iterator().next().getClass());
        if (primaryKeyField == null) {
            throw new IllegalStateException(
                    "Could not find a primary key field annotated with @Id in the given entity type.");
        }
        String entitieName = "";
        Column columnAnnotation = primaryKeyField.getAnnotation(Column.class);
        if (columnAnnotation != null && !columnAnnotation.name().isEmpty()) {
            entitieName =  columnAnnotation.name();
        }
        else {
            entitieName = primaryKeyField.getName();
        }
        // 使用 StringBuilder 构建 DELETE SQL 语句
        StringBuilder sqlBuilder = new StringBuilder("DELETE FROM ");
        sqlBuilder.append(getTableName(entities.iterator().next().getClass()))
                .append(" WHERE ").append(entitieName).append("  = :")
                .append(primaryKeyField.getName());
        //最终执行sql
        batchExecute(sqlBuilder.toString(), entities, entities.size());


    }

    @Override
    public void deleteById(final Serializable id) {
        // 确保实体类上有@Entity注解
        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }
        Field primaryKeyField = findPrimaryKeyField(entityClazz);
        if (primaryKeyField == null) {
            throw new IllegalStateException(
                    "Could not find a primary key field annotated with @Id in the given entity type.");
        }
        // 构建HQL或Criteria删除语句
        StringBuilder sqlBuilder = new StringBuilder().append("DELETE FROM ")
                .append(getTableName(entityClazz)).append(" WHERE ")
                .append(primaryKeyField.getName()).append(" = :id");

        // 设置参数
        DataParam param = new DataParam();
        param.setParamMap(Map.of("id", id));

        // 执行 SQL
        excuteSql(sqlBuilder.toString(), param);
    }

    @Override
    public void deleteByIds(final Collection<? extends Serializable> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {

            // 确保实体类上有@Entity注解
            Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
            if (!entityClazz.isAnnotationPresent(Entity.class)) {
                throw new IllegalArgumentException("The provided class is not an Entity.");
            }
            Field primaryKeyField = findPrimaryKeyField(entityClazz);
            if (primaryKeyField == null) {
                throw new IllegalStateException(
                 "Could not find a primary key field annotated with @Id in the given entity type.");
            }

            // 构建HQL或Criteria删除语句
            StringBuilder sqlBuilder = new StringBuilder().append("DELETE FROM ")
                    .append(getTableName(entityClazz)).append(" WHERE ")
                    .append(primaryKeyField.getName()).append(" IN (:ids)");
            // 设置参数
            DataParam param = new DataParam();
            param.setParamMap(Map.of("ids", ids));

            // 执行 SQL
            excuteSql(sqlBuilder.toString(), param);
        }
    }

    @Override
    public void deleteByLambda(final LambdaDeleteSpecification<T> specification) {
        deleteBySpecification(specification.toSpecification(new LambdaDeleteWrapper<>()));

    }

    @Override
    public void deleteByLambda(final LambdaDeleteWrapper<T> wrapper) {
        deleteBySpecification(wrapper);
    }

    /**
     *
     * @param specification
     * @return T
     */
    @Override
    public T get(final QuerySpecification<T> specification) {
        return getBySpecification(specification.toSpecification(new QueryWrapper<>()));
    }

    /**
     *
     * @param specification
     * @return T
     */
    public T getBySpecification(final AbstractQueryWrapper<T> specification) {
        return (T) getBySpecification(specification, entityClazz);
    }

    /**
     *
     * @param specification
     * @param clazz
     * @return <M> M
     * @param <M>
     */
    public <M> M getBySpecification(final AbstractQueryWrapper<T> specification, final Class<M> clazz) {

        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }
        Assert.notNull(specification, ErrorCodeDef.PARAM_NOT_NULL, "查询条件");
        Map<String, Object> parseEntityNameMap = parseEntityName(entityClazz, true);

        StringBuilder sqlBuilder = new StringBuilder().append("SELECT ");
        DataParam param = new DataParam();
        param.setBeanType(clazz);

        toQueryPredicate(sqlBuilder, parseEntityNameMap, specification, param);

        Object queriedObject = query(sqlBuilder.toString(), param);
        if (SCALAR_TYPES.contains(clazz)) {
            return (M) queriedObject;
        }
        List<M> queried = (List<M>) queriedObject;
        if (CollectionUtils.isEmpty(queried)) {
            return null;
        }
        return queried.get(0);
    }

    private void toQueryPredicate(final StringBuilder sqlBuilder, final Map<String, Object> parseEntityNameMap,
                                  final AbstractQueryWrapper<T> specification, final DataParam param) {
        if (specification.getSelectionList().isEmpty()) {
            sqlBuilder.append(parseEntityNameMap.values().stream()
                    .map(Object::toString) // 将每个对象转换为字符串
                    .collect(Collectors.joining(", "))); // 使用逗号和空格连接
        }
        else {
            for (int i = 0; i < specification.getSelectionList().size(); ++i) {
                if (i > 0) {
                    sqlBuilder.append(", ");
                }
                toSelection(sqlBuilder, parseEntityNameMap, specification.getSelectionList().get(i));
            }
        }
        sqlBuilder.append(" FROM ").append(getTableName(entityClazz)).append(" ");
        toPredicate(specification, parseEntityNameMap, sqlBuilder, param);
        if (MapUtils.isEmpty(param.getParamMap())) {
            param.setParamMap(new HashMap<String, Object>());
        }
        // 处理分组
        if (!specification.getGroupList().isEmpty()) {
            sqlBuilder.append(" GROUP BY ");
            String groupByFields = specification.getGroupList().stream()
                    .map(group -> parseEntityNameMap.getOrDefault(group, group))
                    .map(Object::toString)
                    .collect(Collectors.joining(", "));
            sqlBuilder.append(groupByFields).append(" ");
        }

        // 构建 ORDER BY 子句
        if (!specification.getOrderByList().isEmpty()) {
            sqlBuilder.append(" ORDER BY ");
            String orderByClauses = specification.getOrderByList().stream()
                    .map(order -> {
                        String columnName = parseEntityNameMap.getOrDefault(order.getProperty(),
                                order.getProperty()).toString();
                        return columnName + (order.isDesc() ? " DESC" : " ASC");
                    })
                    .collect(Collectors.joining(", "));
            sqlBuilder.append(orderByClauses);
        }

    }

    private void toSelection(final StringBuilder sqlBuilder, final Map<String, Object> parseEntityNameMap,
                             final TempSelection tempSelection) {
        String columnName = parseEntityNameMap.getOrDefault(tempSelection.getField(),
                tempSelection.getField()).toString();

        switch (tempSelection.getOperator()) {
            case FIELD:
                sqlBuilder.append(columnName);
                break;
            case SUM:
                sqlBuilder.append("SUM(").append(columnName).append(")");
                break;
            case AVG:
                sqlBuilder.append("AVG(").append(columnName).append(")");
                break;
            case COUNT:
                sqlBuilder.append("COUNT(").append(columnName).append(")");
                break;
            case MAX:
                sqlBuilder.append("MAX(").append(columnName).append(")");
                break;
            case MIN:
                sqlBuilder.append("MIN(").append(columnName).append(")");
                break;
            case DIFF:
                if (tempSelection.getField2() != null) {
                    String secondColumnName = parseEntityNameMap.getOrDefault(tempSelection.getField2(),
                            tempSelection.getField2()).toString();
                    sqlBuilder.append("(").append(columnName).append(" - ").append(secondColumnName).append(")");
                }
                else {
                    throw new DaoException(ErrorCodeDef.PARAM_ERROR, "DIFF requires two fields.");
                }
                break;
            case SUMMING:
                if (tempSelection.getField2() != null) {
                    String secondColumnName = parseEntityNameMap.getOrDefault(tempSelection.getField2(),
                            tempSelection.getField2()).toString();
                    sqlBuilder.append("SUM(").append(columnName).append(" + ").append(secondColumnName).append(")");
                }
                else {
                    throw new DaoException(ErrorCodeDef.PARAM_ERROR, "SUMMING requires two fields.");
                }
                break;
            default:
                throw new DaoException(ErrorCodeDef.PARAM_ERROR, tempSelection.getOperator().name());
        }
        // 添加别名（如果有）
        if (StringUtils.isNotEmpty(tempSelection.getAlias())) {
            sqlBuilder.append(" AS ").append(tempSelection.getAlias());
        }

    }


    @Override
    public <M> M get(final QuerySpecification<T> specification, final Class<M> clazz) {
        return getBySpecification(specification.toSpecification(new QueryWrapper<>()), clazz);
    }

    @Override
    public T get(final QueryWrapper<T> wrapper) {
        return getBySpecification(wrapper);
    }

    @Override
    public <M> M get(final QueryWrapper<T> wrapper, final Class<M> clazz) {
        return getBySpecification(wrapper, clazz);
    }

    @Override
    public T get(final Serializable id) {
        // 确保实体类上有@Entity注解
        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }
        Field primaryKeyField = findPrimaryKeyField(entityClazz);
        if (primaryKeyField == null) {
            throw new IllegalStateException(
                    "Could not find a primary key field annotated with @Id in the given entity type.");
        }
        Map<String, Object> stringObjectMap = parseEntityName(entityClazz, false);
        // 构建HQL或Criteria删除语句
        StringBuilder sqlBuilder = new StringBuilder().append("SELECT ")
                .append(String.join(", ", stringObjectMap.keySet()))
                .append(" FROM ").append(getTableName(entityClazz)).append(" WHERE ")
                .append(primaryKeyField.getName()).append(" = :id");

        // 设置参数
        DataParam param = new DataParam();
        param.setParamMap(Map.of("id", id));
        param.setBeanType(entityClazz);
        // 执行 SQL
        List<T> queried = (List<T>) query(sqlBuilder.toString(), param);
        if (CollectionUtils.isEmpty(queried)) {
            return null;
        }
        return queried.get(0);
    }

    @Override
    public <M> M getByLambda(final LambdaQuerySpecification<T, M> specification, final Class<M> clazz) {
        return getBySpecification(specification.toSpecification(new LambdaQueryWrapper<>()), clazz);
    }

    @Override
    public T getByLambda(final LambdaQuerySpecification<T, T> specification) {
        return getBySpecification(specification.toSpecification(new LambdaQueryWrapper<>()));
    }

    @Override
    public <M> M getByLambda(final LambdaQueryWrapper<T, M> wrapper, final Class<M> clazz) {
        return getBySpecification(wrapper, clazz);
    }

    @Override
    public T getByLambda(final LambdaQueryWrapper<T, T> wrapper) {
        return getBySpecification(wrapper);
    }

    @Override
    public List<T> query(final QuerySpecification<T> specification) {
        return queryBySpecification(specification.toSpecification(new QueryWrapper<>()));
    }

    /**
     *
     * @param specification
     * @return List<T>
     */
    private List<T> queryBySpecification(final AbstractQueryWrapper<T> specification) {
        return (List<T>) queryBySpecification(specification, entityClazz);
    }

    /**
     *
     * @param wrapper
     * @param clazz
     * @return <M> List<M>
     * @param <M>
     */
    public <M> List<M> queryBySpecification(final AbstractQueryWrapper<T> wrapper, final Class<M> clazz) {
        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }
        Assert.notNull(wrapper, ErrorCodeDef.PARAM_NOT_NULL, "查询条件");
        Map<String, Object> parseEntityNameMap = parseEntityName(entityClazz, true);

        StringBuilder sqlBuilder = new StringBuilder().append("SELECT ");
        DataParam param = new DataParam();
        param.setBeanType(clazz);
        toQueryPredicate(sqlBuilder, parseEntityNameMap, wrapper, param);
        sqlBuilder.append(" limit ").append(INT1);
        List<M> query = (List<M>) query(sqlBuilder.toString(), param);
        return query;
    }

    private PagerList<T> queryPagerBySpecification(final AbstractQueryWrapper<T> specification,
                                                   final int pageIndex, final int pageSize) {
        return (PagerList<T>) queryPagerBySpecification(specification, pageIndex, pageSize, entityClazz);
    }

    /**
     *
     * @param wrapper
     * @param pi
     * @param pageSize
     * @param clazz
     * @return <M> PagerList<M>
     * @param <M>
     */
    public <M> PagerList<M> queryPagerBySpecification(final AbstractQueryWrapper<T> wrapper, final int pi,
                                                      final int pageSize, final Class<M> clazz) {
        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }
        Assert.notNull(wrapper, ErrorCodeDef.PARAM_NOT_NULL, "查询条件");
        Map<String, Object> parseEntityNameMap = parseEntityName(entityClazz, true);

        StringBuilder sqlBuilder = new StringBuilder().append("SELECT ");
        DataParam param = new DataParam();
        param.setBeanType(clazz);
        toQueryPredicate(sqlBuilder, parseEntityNameMap, wrapper, param);
        param.getParamMap().put(DaoConstants.PAGE_INDEX, pi);
        param.getParamMap().put(DaoConstants.PAGE_SIZE, pageSize);
        PagerList query = (PagerList) query(sqlBuilder.toString(), param);
        return query;
    }

    @Override
    public <M> List<M> query(final QuerySpecification<T> specification, final Class<M> clazz) {
        return queryBySpecification(specification.toSpecification(new QueryWrapper<>()), clazz);
    }

    @Override
    public List<T> query(final QueryWrapper<T> wrapper) {
        return queryBySpecification(wrapper);
    }

    @Override
    public <M> List<M> query(final QueryWrapper<T> wrapper, final Class<M> clazz) {
        return queryBySpecification(wrapper, clazz);
    }

    @Override
    public List<T> queryAll() {
        // 确保实体类上有@Entity注解
        Assert.notNull(entityClazz, ErrorCodeDef.PROXY_TARGET_NOT_FOUND);
        if (!entityClazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalArgumentException("The provided class is not an Entity.");
        }

        List<T> resultList = new ArrayList<>();
        String tableName = getTableName(entityClazz); // 需要实现此方法来获取表名
        Map<String, Object> parseEntityNameMap = parseEntityName(entityClazz, false);

        // 构建HQL或Criteria查询语句
        StringBuilder sqlBuilder = new StringBuilder().append("SELECT ")
                .append(String.join(", ", parseEntityNameMap.keySet()))
                .append(" FROM ").append(tableName).append("").append(" LIMIT 1000");

        DataParam param = new DataParam();
        param.setBeanType(entityClazz);
        param.setParamMap(new HashMap<>());
        param.setReturnType(List.class);
        // 执行 SQL
        List<T> query = (List<T>) query(sqlBuilder.toString(), param);
        return query;
    }

    @Override
    public <M> List<M> queryByLambda(final LambdaQuerySpecification<T, M> specification, final Class<M> clazz) {
        return queryBySpecification(specification.toSpecification(new LambdaQueryWrapper<>()), clazz);
    }

    @Override
    public List<T> queryByLambda(final LambdaQuerySpecification<T, T> specification) {
        return queryBySpecification(specification.toSpecification(new LambdaQueryWrapper<>()));
    }

    @Override
    public <M> List<M> queryByLambda(final LambdaQueryWrapper<T, M> wrapper, final Class<M> clazz) {
        return queryBySpecification(wrapper, clazz);
    }

    @Override
    public List<T> queryByLambda(final LambdaQueryWrapper<T, T> wrapper) {
        return queryBySpecification(wrapper);
    }

    @Override
    public PagerList<T> queryPager(final QuerySpecification<T> specification, final int pageIndex, final int pageSize) {
