SqlSourceBuilder
两个作用:
将"#{xxx}“替换为占位符”?"将占位符"?"对应的属性信息一起构建成到ParameterMapping中,以便在后续ParameterHandler真正地参数赋值。
源码解析
先分析从SqlNode 上下文中得到完成的originalSql,将其中的"#{xxx}“替换为占位符”?"同时为每个"#{xxx}"对应的属性构建对应的ParameterMapping对象。进一步得到一个包含?的完整的SQL语句,最后构建出一个StaticSqlSource对象。
public SqlSource
parse(String originalSql
, Class
<?> parameterType
, Map
<String, Object> additionalParameters
) {
ParameterMappingTokenHandler handler
= new ParameterMappingTokenHandler(configuration
, parameterType
, additionalParameters
);
GenericTokenParser parser
= new GenericTokenParser("#{", "}", handler
);
String sql
= parser
.parse(originalSql
);
return new StaticSqlSource(configuration
, sql
, handler
.getParameterMappings());
}
ParameterMappingTokenHandler
private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
private List
<ParameterMapping> parameterMappings
= new ArrayList<>();
public String
handleToken(String content
) {
parameterMappings
.add(buildParameterMapping(content
));
return "?";
}
private ParameterMapping
buildParameterMapping(String content
) {
Map
<String, String> propertiesMap
= parseParameterMapping(content
);
String property
= propertiesMap
.get("property");
Class
<?> propertyType
;
if (metaParameters
.hasGetter(property
)) {
propertyType
= metaParameters
.getGetterType(property
);
} else if (typeHandlerRegistry
.hasTypeHandler(parameterType
)) {
propertyType
= parameterType
;
} else if (JdbcType
.CURSOR
.name().equals(propertiesMap
.get("jdbcType"))) {
propertyType
= java
.sql
.ResultSet
.class;
} else if (property
== null
|| Map
.class.isAssignableFrom(parameterType
)) {
propertyType
= Object
.class;
} else {
MetaClass metaClass
= MetaClass
.forClass(parameterType
, configuration
.getReflectorFactory());
if (metaClass
.hasGetter(property
)) {
propertyType
= metaClass
.getGetterType(property
);
} else {
propertyType
= Object
.class;
}
}
ParameterMapping
.Builder builder
= new ParameterMapping.Builder(configuration
, property
, propertyType
);
Class
<?> javaType
= propertyType
;
String typeHandlerAlias
= null
;
for (Map
.Entry
<String, String> entry
: propertiesMap
.entrySet()) {
String name
= entry
.getKey();
String value
= entry
.getValue();
if ("javaType".equals(name
)) {
javaType
= resolveClass(value
);
builder
.javaType(javaType
);
} else if ("jdbcType".equals(name
)) {
builder
.jdbcType(resolveJdbcType(value
));
} else if ("mode".equals(name
)) {
builder
.mode(resolveParameterMode(value
));
} else if ("numericScale".equals(name
)) {
builder
.numericScale(Integer
.valueOf(value
));
} else if ("resultMap".equals(name
)) {
builder
.resultMapId(value
);
} else if ("typeHandler".equals(name
)) {
typeHandlerAlias
= value
;
} else if ("jdbcTypeName".equals(name
)) {
builder
.jdbcTypeName(value
);
} else if ("property".equals(name
)) {
} else
......
}
}
if (typeHandlerAlias
!= null
) {
builder
.typeHandler(resolveTypeHandler(javaType
, typeHandlerAlias
));
}
return builder
.build();
}
}