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

titan.lightbatis.mybatis.provider.MapperProvider Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/**
 * 
 */
package titan.lightbatis.mybatis.provider;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import titan.lightbatis.configuration.MapperConfig;
import titan.lightbatis.exception.LightbatisException;
import titan.lightbatis.mybatis.MapperBuilder;
import titan.lightbatis.mybatis.meta.ColumnMeta;
import titan.lightbatis.mybatis.meta.EntityMeta;
import titan.lightbatis.mybatis.meta.EntityMetaManager;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author [email protected]
 *
 */
@Slf4j
public class MapperProvider {
	private static final XMLLanguageDriver languageDriver = new XMLLanguageDriver();
    protected Map methodMap = new ConcurrentHashMap();
    protected Map> entityClassMap = new ConcurrentHashMap>();
    protected Class mapperClass;
    protected MapperBuilder mapperBuilder;

    public MapperProvider(Class mapperClass, MapperBuilder mapperBuilder) {
        this.mapperClass = mapperClass;
        this.mapperBuilder = mapperBuilder;
    }

    /**
     * 根据msId获取接口类
     *
     * @param msId
     * @return
     */
    public static Class getMapperClass(String msId) {
        if (msId.indexOf(".") == -1) {
            throw new LightbatisException("当前MappedStatement的id=" + msId + ",不符合MappedStatement的规则!");
        }
        String mapperClassStr = msId.substring(0, msId.lastIndexOf("."));
        try {
            return Class.forName(mapperClassStr);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    /**
     * 获取执行的方法名
     *
     * @param ms
     * @return
     */
    public static String getMethodName(MappedStatement ms) {
        return getMethodName(ms.getId());
    }

    /**
     * 获取执行的方法名
     *
     * @param msId
     * @return
     */
    public static String getMethodName(String msId) {
        return msId.substring(msId.lastIndexOf(".") + 1);
    }

    /**
     * 该方法仅仅用来初始化ProviderSqlSource
     *
     * @param record
     * @return
     */
    public String dynamicSQL(Object record) {
        return "dynamicSQL";
    }

    /**
     * 添加映射方法
     *
     * @param methodName
     * @param method
     */
    public void addMethodMap(String methodName, Method method) {
        methodMap.put(methodName, method);
    }

    /**
     * 是否支持该通用方法
     *
     * @param msId
     * @return
     */
    public boolean supportMethod(String msId) {
        Class mapperClass = getMapperClass(msId);
        if (mapperClass != null && this.mapperClass.isAssignableFrom(mapperClass)) {
            String methodName = getMethodName(msId);
            return methodMap.get(methodName) != null;
        }
        return false;
    }

    /**
     * 设置返回值类型 - 为了让typeHandler在select时有效,改为设置resultMap
     *
     * @param ms
     * @param entityClass
     */
    protected void setResultType(MappedStatement ms, Class entityClass) {
        EntityMeta entityTable = EntityMetaManager.getEntityMeta(entityClass);
        List resultMaps = new ArrayList();
        resultMaps.add(entityTable.getResultMap(ms.getConfiguration()));
        MetaObject metaObject = SystemMetaObject.forObject(ms);
        metaObject.setValue("resultMaps", Collections.unmodifiableList(resultMaps));
    }

    /**
     * 重新设置SqlSource
     *
     * @param ms
     * @param sqlSource
     */
    protected void setSqlSource(MappedStatement ms, SqlSource sqlSource) {
        MetaObject msObject = SystemMetaObject.forObject(ms);
        msObject.setValue("sqlSource", sqlSource);

    }



    /**
     * 重新设置SqlSource
     *
     * @param ms
     * @throws java.lang.reflect.InvocationTargetException
     * @throws IllegalAccessException
     */
    public void setSqlSource(MappedStatement ms) throws Exception {
        if (this.mapperClass == getMapperClass(ms.getId())) {
            throw new LightbatisException("请不要配置或扫描通用Mapper接口类:" + this.mapperClass);
        }
        Method method = methodMap.get(getMethodName(ms));
        try {
            //第一种,直接操作ms,不需要返回值
            if (method.getReturnType() == Void.TYPE) {
                method.invoke(this, ms);
            }
            //第二种,返回SqlNode
            else if (SqlNode.class.isAssignableFrom(method.getReturnType())) {
                SqlNode sqlNode = (SqlNode) method.invoke(this, ms);
                DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode);
                setSqlSource(ms, dynamicSqlSource);
            } else if (SqlSource.class.isAssignableFrom(method.getReturnType())) {
                SqlSource sqlSource = (SqlSource) method.invoke(this, ms);
                setSqlSource(ms, sqlSource);
            }
            //第三种,返回xml形式的sql字符串
            else if (String.class.equals(method.getReturnType())) {
                try{
                    String xmlSql = (String) method.invoke(this, ms);
                    SqlSource sqlSource = createSqlSource(ms, xmlSql);
                    //替换原有的SqlSource
                    setSqlSource(ms, sqlSource);
                } catch (Exception ex) {
                    ex.printStackTrace(System.err);
                    //throw new LightbatisException(ex);
                }

            } else {
                throw new LightbatisException("自定义Mapper方法返回类型错误,可选的返回类型为void,SqlNode,String三种!");
            }
            //cache
           // checkCache(ms);
        } catch (IllegalAccessException e) {
            throw new LightbatisException(e);
        } catch (InvocationTargetException e) {
            throw new LightbatisException(e.getTargetException() != null ? e.getTargetException() : e);
        }
    }

    /**
     * 通过xmlSql创建sqlSource
     *
     * @param ms
     * @param xmlSql
     * @return
     */
    public SqlSource createSqlSource(MappedStatement ms, String xmlSql) {
        return languageDriver.createSqlSource(ms.getConfiguration(), "", null);
    }

    /**
     * 获取返回值类型 - 实体类型
     *
     * @param ms
     * @return
     */
    public Class getEntityClass(MappedStatement ms) {
        String msId = ms.getId();
        if (entityClassMap.containsKey(msId)) {
            return entityClassMap.get(msId);
        } else {
            Class mapperClass = getMapperClass(msId);
            Type[] types = mapperClass.getGenericInterfaces();
            for (Type type : types) {
                if (type instanceof ParameterizedType) {
                    ParameterizedType t = (ParameterizedType) type;
                    if (t.getRawType() == this.mapperClass || this.mapperClass.isAssignableFrom((Class) t.getRawType())) {
                        Class returnType = (Class) t.getActualTypeArguments()[0];
                        //获取该类型后,第一次对该类型进行初始化
                        try {
							EntityMetaManager.initEntityNameMap(returnType, mapperBuilder.getConfig(), msId);
	                        entityClassMap.put(msId, returnType);
	                        return returnType;
						} catch (Exception e) {
							e.printStackTrace(System.err);
							throw new LightbatisException("无法获取Mapper泛型类型:" + msId);
						}
                    }
                }
            }
        }
        throw new LightbatisException("无法获取Mapper泛型类型:" + msId);
    }

    protected static void setKeyGenerator(MappedStatement ms, ColumnMeta column, KeyGenerator keyGenerator) {
        //keyGenerator
        try {
            String table = column.getTableName();
            EntityMeta entityMeta = EntityMetaManager.getEntityMetaByTable(table);
            if (entityMeta == null) {
                entityMeta = EntityMetaManager.getEntityMeta(ms.getId());
            }
            MetaObject msObject = SystemMetaObject.forObject(ms);
            msObject.setValue("keyGenerator", keyGenerator);
            msObject.setValue("keyProperties", entityMeta.getKeyProperties());
            msObject.setValue("keyColumns", entityMeta.getKeyColumns());
        } catch (Exception e) {
            //ignore
            log.warn(e.getMessage());
        }
    }

    /**
     * 获取实体类的表名
     *
     * @param entityClass
     * @return
     */
    protected String tableName(Class entityClass) {
        EntityMeta entityTable = EntityMetaManager.getEntityMeta(entityClass);
        String prefix = entityTable.getPrefix();
        if (StringUtils.isEmpty(prefix)) {
            //使用全局配置
            prefix = mapperBuilder.getConfig().getPrefix();
        }
        if (StringUtils.isNotEmpty(prefix)) {
            return prefix + "." + entityTable.getName();
        }
        return entityTable.getName();
    }

    public MapperConfig getConfig() {
        return mapperBuilder.getConfig();
    }
    public boolean isNotEmpty() {
        return getConfig().isNotEmpty();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy