participant A as XMLMapperBuilder
participant B as MapperBuilderAssistant
participant C as ParameterMapping
participant D as TypeHandlerRegistry
A ->> B : buildParameterMapping
B ->> C : Builder
B ->> C : build
C ->> C : resolveTypeHandler
C ->> D : getTypeHandler
D ->> D : getJdbcHandlerMap
D -->> C : TypeHandler
C -->> A : ParameterMapping
XMLMapperBuilder#configurationElement
* 解析映射文件的下层节点
*
@param
context 映射文件根节点
private
void
configurationElement
(XNode context)
{
try
{
String
namespace
=
context.getStringAttribute(
"namespace"
);
if
(namespace ==
null
|| namespace.equals(
""
)) {
throw
new
BuilderException
(
"Mapper's namespace cannot be empty"
);
builderAssistant.setCurrentNamespace(namespace);
cacheRefElement(context.evalNode(
"cache-ref"
));
cacheElement(context.evalNode(
"cache"
));
parameterMapElement(context.evalNodes(
"/mapper/parameterMap"
));
resultMapElements(context.evalNodes(
"/mapper/resultMap"
));
sqlElement(context.evalNodes(
"/mapper/sql"
));
buildStatementFromContext(context.evalNodes(
"select|insert|update|delete"
));
}
catch
(Exception e) {
throw
new
BuilderException
(
"Error parsing Mapper XML. The XML location is '"
+ resource +
"'. Cause: "
+ e, e);
XMLMapperBuilder#parameterMapElement
* 参数映射解析
private
void
parameterMapElement
(List<XNode> list)
{
for
(XNode parameterMapNode : list) {
String
id
=
parameterMapNode.getStringAttribute(
"id"
);
String
type
=
parameterMapNode.getStringAttribute(
"type"
);
Class<?> parameterClass = resolveClass(type);
List<XNode> parameterNodes = parameterMapNode.evalNodes(
"parameter"
);
List<ParameterMapping> parameterMappings =
new
ArrayList
<>();
for
(XNode parameterNode : parameterNodes) {
String
property
=
parameterNode.getStringAttribute(
"property"
);
String
javaType
=
parameterNode.getStringAttribute(
"javaType"
);
String
jdbcType
=
parameterNode.getStringAttribute(
"jdbcType"
);
String
resultMap
=
parameterNode.getStringAttribute(
"resultMap"
);
String
mode
=
parameterNode.getStringAttribute(
"mode"
);
String
typeHandler
=
parameterNode.getStringAttribute(
"typeHandler"
);
Integer
numericScale
=
parameterNode.getIntAttribute(
"numericScale"
);
ParameterMode
modeEnum
=
resolveParameterMode(mode);
Class<?> javaTypeClass = resolveClass(javaType);
JdbcType
jdbcTypeEnum
=
resolveJdbcType(jdbcType);
Class<?
extends
TypeHandler
<?>> typeHandlerClass = resolveClass(typeHandler);
ParameterMapping
parameterMapping
=
builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
parameterMappings.add(parameterMapping);
builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
MapperBuilderAssistant#buildParameterMapping
如果javaType为null,则通过反射解析
创建
ParameterMapping
对象并返回
创建对象时,根据javaType、jdbcType解析类型处理器
public ParameterMapping buildParameterMapping(
Class<?> parameterType,
String property,
Class<?> javaType,
JdbcType jdbcType,
String resultMap,
ParameterMode parameterMode,
Class<? extends TypeHandler<?>> typeHandler,
Integer numericScale) {
resultMap = applyCurrentNamespace(resultMap, true);
Class<?> javaTypeClass = resolveParameterJavaType(parameterType, property, javaType, jdbcType);
TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
return new ParameterMapping.Builder(configuration, property, javaTypeClass)
.jdbcType(jdbcType)
.resultMapId(resultMap)
.mode(parameterMode)
.numericScale(numericScale)
.typeHandler(typeHandlerInstance)
.build();
ParameterMapping#Builder
public Builder(Configuration configuration, String property, Class<?> javaType) {
parameterMapping.configuration = configuration;
parameterMapping.property = property;
parameterMapping.javaType = javaType;
parameterMapping.mode = ParameterMode.IN;
ParameterMapping#build
public ParameterMapping build() {
resolveTypeHandler();
validate();
return parameterMapping;
ParameterMapping#resolveTypeHandler
private void resolveTypeHandler() {
if (parameterMapping.typeHandler == null && parameterMapping.javaType != null) {
Configuration configuration = parameterMapping.configuration;
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
parameterMapping.typeHandler = typeHandlerRegistry.getTypeHandler(parameterMapping.javaType, parameterMapping.jdbcType);
TypeHandlerRegistry#getTypeHandler
* 找出一个类型处理器
* @param type Java类型
* @param jdbcType JDBC类型
* @param <T> 类型处理器的目标类型
* @return 类型处理器
@SuppressWarnings("unchecked")
private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
if (ParamMap.class.equals(type)) {
return null;
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
handler = jdbcHandlerMap.get(null);
if (handler == null) {
handler = pickSoleHandler(jdbcHandlerMap);
return (TypeHandler<T>) handler;
TypeHandlerRegistry#getJdbcHandlerMap
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
return null;
if (jdbcHandlerMap == null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
if (Enum.class.isAssignableFrom(clazz)) {
Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
if (jdbcHandlerMap == null) {
register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
return typeHandlerMap.get(enumClass);
} else {
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
return jdbcHandlerMap;
以上便是Mybatis解析parameterMap标签的过程。