All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sf.database.mapper.handle.MethodHandleTemplate Maven / Gradle / Ivy

The newest version!
package sf.database.mapper.handle;

import sf.common.wrapper.Page;
import sf.database.dao.DBClient;
import sf.database.mapper.MapperInvoke;
import sf.database.mapper.annotation.ExecuteTemplate;
import sf.database.mapper.annotation.OrmParam;
import sf.database.mapper.annotation.SelectKey;
import sf.database.mapper.annotation.SqlResource;
import sf.database.support.DMLType;
import sf.database.template.CType;
import sf.tools.ArrayUtils;
import sf.tools.JavaTypeUtils;
import sf.tools.StringUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 接口执行模板
 */
public class MethodHandleTemplate implements MapperInvoke {
    protected static MethodHandleTemplate ms = new MethodHandleTemplate();

    public static MethodHandleTemplate getInstance() {
        return ms;
    }

    private MethodHandleTemplate() {

    }

    @Override
    public Object call(DBClient dbClient, Class entityClass, Method m, Object[] params) {
        Object ret = null;
        SqlResource resource = m.getDeclaringClass().getAnnotation(SqlResource.class);
        ExecuteTemplate et = m.getAnnotation(ExecuteTemplate.class);
        String sqlId = et.id();
        String sql = StringUtils.join(et.value());
        //是否是sqlid
        boolean isSqlId = true;

        if (StringUtils.isNotBlank(sqlId)) {
            sql = sqlId;
        } else if (StringUtils.isNotBlank(sql)) {
            isSqlId = false;
        } else {
            if (StringUtils.isBlank(sqlId)) {
                if (resource != null) {
                    String preffix = resource.value();
                    String name = m.getName();
                    sqlId = preffix + "." + name;
                } else {
                    sqlId = m.getName();
                }
            }
            sql = sqlId;
        }

        switch (et.type()) {
            case SELECT:
                ret = parseSelectList(m, dbClient, sql, params, isSqlId);
                break;
            case INSERT:
                ret = parseInsert(m, dbClient, sql, params, et.batch(), isSqlId);
                break;
            default:
                ret = parseUpdate(m, dbClient, sql, params, isSqlId);
                break;
        }
        return ret;
    }

    public Object call(DBClient dbClient, Method m, String sqlTemplate, DMLType dmlType, Object[] params) {
        Object ret = null;
        //是否是sqlid
        boolean isSqlId = false;
        boolean isBatch = false;
        switch (dmlType) {
            case SELECT:
                ret = parseSelectList(m, dbClient, sqlTemplate, params, isSqlId);
                break;
            case INSERT:
                ret = parseInsert(m, dbClient, sqlTemplate, params, isBatch, isSqlId);
                break;
            default:
                ret = parseUpdate(m, dbClient, sqlTemplate, params, isSqlId);
                break;
        }
        return ret;
    }


    protected Object parseInsert(Method method, DBClient dbClient, String sql, Object[] params, boolean batch, boolean isSqlId) {
        SelectKey returnKey = method.getAnnotation(SelectKey.class);
        List pkeys = Collections.emptyList();
        if (returnKey != null && StringUtils.isNotBlank(returnKey.keyColumn())) {
            pkeys = Collections.singletonList(returnKey.keyColumn());
        }


        Map paraMap = new LinkedHashMap<>();
        convertParam(method, params, paraMap);

        List> rMap = new LinkedList<>();
        List> pa = new ArrayList<>();
        if (!batch) {
            pa.add(paraMap);
        } else {
            if (params != null && params.length > 0) {
                pa.addAll((Collection>) params[0]);
            }
        }
        CType cType = isSqlId ? CType.id : CType.source;
        dbClient.executeBatchTemplate(sql, cType, pa, false, 100, pkeys, rMap);


        if (!rMap.isEmpty() && returnKey != null) {
            Object value = rMap.get(0).values().iterator().next();
            if (returnKey.resultType() == Integer.class || returnKey.resultType() == int.class) {
                return ((Number) value).intValue();
            } else if (returnKey.resultType() == Long.class || returnKey.resultType() == long.class) {
                return ((Number) value).longValue();
            } else if (returnKey.resultType() == Map.class) {
                return rMap.get(0);
            }
        }
        return null;
    }

    /**
     * 根据返回参数int 或者int[] 判断是否是批处理。如果都没有,根据第一参数判断
     * @param method
     * @param dbClient
     * @param sql
     * @param params
     * @param isSqlId
     * @return
     */
    protected Object parseUpdate(Method method, DBClient dbClient, String sql, Object[] params, boolean isSqlId) {
        CType cType = isSqlId ? CType.id : CType.source;

        Class[] paras = method.getParameterTypes();
        Class ret = method.getReturnType();
        boolean batch = false;
        if (JavaTypeUtils.isInt(ret)) {
            batch = false;
        } else if (ret.isArray()) {
            //如果更新语句返回了int[],
            Class type = ret.getComponentType();
            if (JavaTypeUtils.isInt(type)) {
                batch = true;
            }
        }
        //通过输入参数判断
        if (paras.length == 1) {
            Class first = paras[0];
            if (List.class.isAssignableFrom(first) && this.isUpdateBatchByFirstList(method)) {
                batch = true;
            } else if (first.isArray()) {
                Class ct = first.getComponentType();
                if (this.isPojo(ct)) {
                    batch = true;
                }
            }
        }
        if (batch) {
            return dbClient.executeBatchTemplate(sql, cType, (List>) params[0]);
        } else {
            Map paraMap = new LinkedHashMap<>();
            convertParam(method, params, paraMap);
            return dbClient.executeTemplate(sql, cType, paraMap);
        }
    }

    private boolean isUpdateBatchByFirstList(Method method) {

        Type firstType = method.getGenericParameterTypes()[0];
        Class type = HandleHelp.getType(firstType);
        if (type == null) {
            //不知道List里面是什么,认为是batchUpdate,兼容以前情况
            return true;
        }
        return isPojo(type);

    }

    private boolean isPojo(Class type) {
        if (type.isPrimitive()) {
            return false;
        }
        if (Map.class.isAssignableFrom(type)) {
            return true;
        }

        String pkg = getPackageName(type);
        if (pkg.startsWith("java.") || pkg.startsWith("javax.")) {
            return false;
        } else {
            return true;
        }
    }

    public static String getPackageName(Class clazz) {
        return StringUtils.substringBefore(clazz.getName(), ".");
    }

    protected Object parseSelectList(Method method, DBClient dbClient, String sql, Object[] paras, boolean isSqlId) {
        if (paras == null) {
            paras = ArrayUtils.EMPTY_OBJECT_ARRAY;
        }
        CType cType = isSqlId ? CType.id : CType.source;
        Class returnType = method.getReturnType();
        Type retType = method.getGenericReturnType();
        Map paraMap = new LinkedHashMap<>();
        RowLimit rl = convertParam(method, paras, paraMap);
        if (returnType == Page.class) {
            Class resultType = HandleHelp.getPageType(retType, Map.class);
            return dbClient.selectPageTemplate(rl.getOffset(), rl.getLimit(), resultType, sql, cType, paraMap);
            //else否则就默认为mapper类型
        }
        if (Map.class.isAssignableFrom(returnType)) {
            //如果定义返回结果为Map,无论是否泛型,都认为返回一个Map
            return dbClient.selectOneTemplate(Map.class, sql, cType, paraMap);
        } else if (List.class.isAssignableFrom(returnType)) {
            Class type = HandleHelp.getType(retType);
            if (type == null) {
                type = Map.class;
            }
            return dbClient.selectListTemplate(type, sql, cType, paraMap);
        }
        //更改类型为Single
        return dbClient.selectOneTemplate(returnType, sql, cType, paraMap);
    }

    private RowLimit convertParam(Method method, Object[] paras, Map paraMap) {
        Class[] paraClass = method.getParameterTypes();
        Parameter[] parameters = method.getParameters();
        RowLimit rl = null;
        if (paras != null) {
            for (int i = 0; i < paraClass.length; i++) {
                Class clz = paraClass[i];
                if (Map.class.isAssignableFrom(clz)) {
                    paraMap.putAll((Map) paras[i]);
                } else if (clz == RowLimit.class) {
                    rl = (RowLimit) paras[i];
                } else {
                    OrmParam p = parameters[i].getAnnotation(OrmParam.class);
                    if (p != null) {
                        paraMap.put(p.value(), paras[i]);
                    } else {
                        paraMap.put(parameters[i].getName(), paras[i]);
                    }
                }
            }
        }
        return rl;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy