
titan.lightbatis.mybatis.provider.MapperProvider Maven / Gradle / Ivy
/**
*
*/
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