前言
书承上文,这一节来分析下SqlMapConfig.xml
中sqlMap
节点中配置的Hero.xml
配置文件,该配置文件中对应了Java
实体类对应数据库SQL
的映射。
示例
t_hero:
CREATE TABLE `t_hero` (
`heroId` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`type` tinyint(2) NOT NULL,
PRIMARY KEY (`heroId`)
) ENGINE=InnoDB AUTO_INCREMENT=10003 DEFAULT CHARSET=utf8 COMMENT='英雄表';
Hero.java:
public class Hero implements Serializable {
private Integer heroId;
private String name;
private Integer type;
}
Hero.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<cacheModel id="heroCache" type="LRU"/>
<typeAlias alias="Hero" type="com.think.domain.Hero" />
<resultMap id="heroMap" class="Hero">
<result property="heroId" column="heroId"/>
<result property="name" column="name"/>
<result property="type" column="type"/>
</resultMap>
<parameterMap id="queryHeroMap" class="Hero">
<parameter property="heroId"/>
</parameterMap>
<insert id="addHero" parameterClass="com.think.domain.Hero">
insert into t_hero values(#heroId#,#name#,#type#)
</insert>
<select id="getById" parameterClass="int" resultClass="Hero">
select * from t_hero where heroId = #heroId#
</select>
<delete id="deleteById" parameterClass="int">
delete from t_hero where heroId= #heroId#
</delete>
<update id="updateById" parameterClass="Hero">
update t_hero set `name`=#name#,`type`=#type# where heroId = #heroId#
</update>
</sqlMap>
StartMain:
public class StartMain {
private static final Logger log = LoggerFactory.getLogger(App.class);
private static final String CONFIG_FILE = "SqlMapConfig.xml";
public static void main(String[] args) throws Exception {
Reader reader = Resources.getResourceAsReader(CONFIG_FILE);
SqlMapClient sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
log.info("Get sql map client: {}", sqlMapClient);
Hero luban7 = new Hero(10001, "鲁班七号", 3);
sqlMapClient.insert("addHero", luban7);
log.info("add Hero: {}", luban7);
Hero hero = (Hero) sqlMapClient.queryForObject("getById", luban7.getHeroId());
log.info("hero: {}", hero);
hero.setName("鲁班8号");
int ret = sqlMapClient.update("updateById", hero);
log.info("update Hero: {}", ret);
hero = (Hero) sqlMapClient.queryForObject("getById", hero.getHeroId());
log.info("hero: {}", hero);
ret = sqlMapClient.delete("deleteById", hero.getHeroId());
log.info("delete hero, {}", ret);
}
}
源码解析
在源码解析之前,我们先来看看上一节中SqlMapConfig.xml
配置文件中注册sqlMap
节点解析的源码,位置在com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser#addSqlMapNodelets
:
protected void addSqlMapNodelets() {
parser.addNodelet("/sqlMapConfig/sqlMap", new Nodelet() {
public void process(Node node) throws Exception {
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//指定的配置文件路径
String resource = attributes.getProperty("resource");
String url = attributes.getProperty("url");
Reader reader = null;
if (resource != null) {
reader = Resources.getResourceAsReader(resource);
} else if (url != null) {
reader = Resources.getUrlAsReader(url);
} else {
throw new SqlMapException("The <sqlMap> element requires either a resource or a url attribute.");
}
//将配置文件输入流交个SqlMapParser进行解析
new SqlMapParser(state).parse(reader);
}
});
}
我们先来看看SqlMapParser
对象的大致结构以及构造方法:
public class SqlMapParser {
//节点解析器,和SqlMapConfigParser结构一致
private final NodeletParser parser;
//数据存储,和SqlMapConfigParser结构一致
private XmlParserState state;
//SQL语句解析
private SqlStatementParser statementParser;
//通过构造函数传递一个SqlMapConfig中的数据解析存储
public SqlMapParser(XmlParserState state) {
this.parser = new NodeletParser();
this.state = state;
//开启文档校验
parser.setValidation(true);
//设置本地类路径的sqlMap解析
parser.setEntityResolver(new SqlMapClasspathEntityResolver());
//创建一个Sql语句解析器
statementParser = new SqlStatementParser(this.state);
//注册/sqlMapConfig/end()节点
addSqlMapNodelets();
///注册sqlMap/sql节点
addSqlNodelets();
///注册sqlMap/typeAlias节点
addTypeAliasNodelets();
//注册/sqlMap/cacheModel节点
addCacheModelNodelets();
//注册/sqlMap/parameterMap节点
addParameterMapNodelets();
//注册/sqlMap/resultMap节点
addResultMapNodelets();
//注册/sqlMap/statement节点(包括/sqlMap/insert,/sqlMap/update,/sqlMap/delete,/sqlMap/select,/sqlMap/procedure节点)
addStatementNodelets();
}
}
addSqlMapNodelets:
private void addSqlMapNodelets() {
parser.addNodelet("/sqlMap", new Nodelet() {
public void process(Node node) throws Exception {
//获取节点上的属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//设置命名空间
state.setNamespace(attributes.getProperty("namespace"));
}
});
}
addSqlNodelets:
private void addSqlNodelets() {
parser.addNodelet("/sqlMap/sql", new Nodelet() {
public void process(Node node) throws Exception {
//解析标签上的节点属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//获取该标签的id
String id = attributes.getProperty("id");
//如果有命名空间则添加上命名空间
if (state.isUseStatementNamespaces()) {
id = state.applyNamespace(id);
}
//重复id检查
if (state.getSqlIncludes().containsKey(id)) {
throw new SqlMapException("Duplicate <sql>-include '" + id + "' found.");
} else {
//将该sql放入到sqlIncludes的Map集合中
state.getSqlIncludes().put(id, node);
}
}
});
}
addTypeAliasNodelets:
private void addTypeAliasNodelets() {
parser.addNodelet("/sqlMap/typeAlias", new Nodelet() {
public void process(Node node) throws Exception {
//货物节点属性
Properties prop = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//别名
String alias = prop.getProperty("alias");
//类全限定名
String type = prop.getProperty("type");
//将其放入到SqlMapConfiguration的TypeHandlerFactory对象中typeAliases集合中
state.getConfig().getTypeHandlerFactory().putTypeAlias(alias, type);
}
});
}
addTypeAliasNodelets用于将一个类名定义一个别名,后期可以减少输入一长串的字符。
addCacheModelNodelets:
private void addCacheModelNodelets() {
parser.addNodelet("/sqlMap/cacheModel", new Nodelet() {
public void process(Node node) throws Exception {
//获取节点属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//缓存节点id
String id = state.applyNamespace(attributes.getProperty("id"));
//缓存类型(FIFO、LRU、MEMORY、OSCACHE)
String type = attributes.getProperty("type");
//该缓存是否只读
String readOnlyAttr = attributes.getProperty("readOnly");
Boolean readOnly = readOnlyAttr == null || readOnlyAttr.length() <= 0 ? null : new Boolean("true".equals(readOnlyAttr));
//该缓存是否可序列化
String serializeAttr = attributes.getProperty("serialize");
Boolean serialize = serializeAttr == null || serializeAttr.length() <= 0 ? null : new Boolean("true".equals(serializeAttr));
//通过该缓存类型定位到具体的缓存全限定类,该缓存的注册在SqlMapConfiguration#registerDefaultTypeAliases
type = state.getConfig().getTypeHandlerFactory().resolveAlias(type);
//加载该class
Class clazz = Resources.classForName(type);
if (readOnly == null) {
readOnly = Boolean.TRUE;
}
if (serialize == null) {
serialize = Boolean.FALSE;
}
//实例化一个CacheModel并将其添加到SqlMapExecutorDelegate的cacheModels的Map集合中,并返回CacheModelConfig实例对象
CacheModelConfig cacheConfig = state.getConfig().newCacheModelConfig(id, (CacheController) Resources.instantiate(clazz), readOnly.booleanValue(), serialize.booleanValue());
//设置当前的CacheModelConfig
state.setCacheConfig(cacheConfig);
}
});
//用于处理cacheModel标签结束后调用
parser.addNodelet("/sqlMap/cacheModel/end()", new Nodelet() {
public void process(Node node) throws Exception {
//设置当前CacheModelConfig的缓存属性
state.getCacheConfig().setControllerProperties(state.getCacheProps());
}
});
//用于处理cacheModel下节点的property属性节点
parser.addNodelet("/sqlMap/cacheModel/property", new Nodelet() {
public void process(Node node) throws Exception {
//获取节点属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//属性名
String name = attributes.getProperty("name");
//属性值
String value = NodeletUtils.parsePropertyTokens(attributes.getProperty("value"), state.getGlobalProps());
//将节点的属性名和属性值放入到Properties集合中
state.getCacheProps().setProperty(name, value);
}
});
//用于处理cacheModel下节点的flushOnExecute属性节点(语句执行触发刷新缓存)
parser.addNodelet("/sqlMap/cacheModel/flushOnExecute", new Nodelet() {
public void process(Node node) throws Exception {
//获取节点属性
Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//语句id
String statement = childAttributes.getProperty("statement");
//添加执行该语句时触发缓存刷新
state.getCacheConfig().addFlushTriggerStatement(statement);
}
});
//用于处理cacheModel下节点的flushInterval属性节点(缓存刷新间隔)
parser.addNodelet("/sqlMap/cacheModel/flushInterval", new Nodelet() {
public void process(Node node) throws Exception {
//节点属性
Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//间隔时间(毫秒)
int milliseconds = childAttributes.getProperty("milliseconds") == null ? 0 : Integer.parseInt(childAttributes.getProperty("milliseconds"));
//间隔时间(秒)
int seconds = childAttributes.getProperty("seconds") == null ? 0 : Integer.parseInt(childAttributes.getProperty("seconds"));
//间隔时间(分)
int minutes = childAttributes.getProperty("minutes") == null ? 0 : Integer.parseInt(childAttributes.getProperty("minutes"));
//间隔时间(小时)
int hours = childAttributes.getProperty("hours") == null ? 0 : Integer.parseInt(childAttributes.getProperty("hours"));
//设置该缓存的刷新间隔
state.getCacheConfig().setFlushInterval(hours, minutes, seconds, milliseconds);
}
});
}
可以看到该方法是用于配置iBatis
的一个缓存。
addParameterMapNodelets:
private void addParameterMapNodelets() {
//处理/sqlMap/parameterMap节点结束
parser.addNodelet("/sqlMap/parameterMap/end()", new Nodelet() {
public void process(Node node) throws Exception {
state.setParamConfig(null);
}
});
//处理/sqlMap/parameterMap节点
parser.addNodelet("/sqlMap/parameterMap", new Nodelet() {
public void process(Node node) throws Exception {
//获取节点属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//节点id
String id = state.applyNamespace(attributes.getProperty("id"));
//参数对应的全限定类名/别名
String parameterClassName = attributes.getProperty("class");
//通过别名定位java全限定类名
parameterClassName = state.getConfig().getTypeHandlerFactory().resolveAlias(parameterClassName);
//实例化一个参数集合配置对象(内部实例化了ParameterMap对象并将其添加到SqlMapExecutorDelegate中parameterMaps集合中)
ParameterMapConfig paramConf = state.getConfig().newParameterMapConfig(id, Resources.classForName(parameterClassName));
state.setParamConfig(paramConf);
}
});
//解析/sqlMap/parameterMap/parameter节点
parser.addNodelet("/sqlMap/parameterMap/parameter", new Nodelet() {
public void process(Node node) throws Exception {
//解析标签属性
Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//属性名
String propertyName = childAttributes.getProperty("property");
//数据库类型
String jdbcType = childAttributes.getProperty("jdbcType");
//类型名
String type = childAttributes.getProperty("typeName");
//java对应的数据类型
String javaType = childAttributes.getProperty("javaType");
//结果集合
String resultMap = state.applyNamespace(childAttributes.getProperty("resultMap"));
String nullValue = childAttributes.getProperty("nullValue");
String mode = childAttributes.getProperty("mode");
//类型处理器
String callback = childAttributes.getProperty("typeHandler");
//浮点数精度
String numericScaleProp = childAttributes.getProperty("numericScale");
//通过别名定位类型处理器
callback = state.getConfig().getTypeHandlerFactory().resolveAlias(callback);
Object typeHandlerImpl = null;
if (callback != null) {
typeHandlerImpl = Resources.instantiate(callback);
}
javaType = state.getConfig().getTypeHandlerFactory().resolveAlias(javaType);
Class javaClass = null;
if (javaType != null && javaType.length() > 0) {
javaClass = Resources.classForName(javaType);
}
Integer numericScale = null;
if (numericScaleProp != null) {
numericScale = new Integer(numericScaleProp);
}
//将参数字段添加到ParameterMapConfig对象的parameterMappingList集合中(用于将数据库字段和java属性字段映射过程)
state.getParamConfig().addParameterMapping(propertyName, javaClass, jdbcType, nullValue, mode, type, numericScale, typeHandlerImpl, resultMap);
}
});
}
addResultMapNodelets:
private void addResultMapNodelets() {
//注册/sqlMap/resultMap节点结束处理
parser.addNodelet("/sqlMap/resultMap/end()", new Nodelet() {
public void process(Node node) throws Exception {
state.getConfig().getErrorContext().setMoreInfo(null);
state.getConfig().getErrorContext().setObjectId(null);
}
});
//注册/sqlMap/resultMap节点处理
parser.addNodelet("/sqlMap/resultMap", new Nodelet() {
public void process(Node node) throws Exception {
//节点属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//结果集id
String id = state.applyNamespace(attributes.getProperty("id"));
//结果对应的java实体类(别名或者全限定类名)
String resultClassName = attributes.getProperty("class");
//继承的结果集
String extended = state.applyNamespace(attributes.getProperty("extends"));
String xmlName = attributes.getProperty("xmlName");
String groupBy = attributes.getProperty("groupBy");
//通过别名定位java全限定类名
resultClassName = state.getConfig().getTypeHandlerFactory().resolveAlias(resultClassName);
//加载类
Class resultClass = Resources.classForName(resultClassName);
//实例化ResultMapConfig对象,内部实例化ResultMap并将其添加到SqlMapExecutorDelegate对象的resultMaps集合中
ResultMapConfig resultConf = state.getConfig().newResultMapConfig(id, resultClass, groupBy, extended, xmlName);
state.setResultConfig(resultConf);
}
});
//注册/sqlMap/resultMap/result节点处理
parser.addNodelet("/sqlMap/resultMap/result", new Nodelet() {
public void process(Node node) throws Exception {
//获取节点属性
Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//属性名
String propertyName = childAttributes.getProperty("property");
String nullValue = childAttributes.getProperty("nullValue");
String jdbcType = childAttributes.getProperty("jdbcType");
String javaType = childAttributes.getProperty("javaType");
//数据库列名
String columnName = childAttributes.getProperty("column");
//数据库列索引
String columnIndexProp = childAttributes.getProperty("columnIndex");
String statementName = childAttributes.getProperty("select");
String resultMapName = childAttributes.getProperty("resultMap");
String callback = childAttributes.getProperty("typeHandler");
String notNullColumn = childAttributes.getProperty("notNullColumn");
Class javaClass = null;
javaType = state.getConfig().getTypeHandlerFactory().resolveAlias(javaType);
if (javaType != null && javaType.length() > 0) {
javaClass = Resources.classForName(javaType);
}
Object typeHandlerImpl = null;
if (callback != null && callback.length() > 0) {
callback = state.getConfig().getTypeHandlerFactory().resolveAlias(callback);
typeHandlerImpl = Resources.instantiate(callback);
}
Integer columnIndex = null;
if (columnIndexProp != null) {
columnIndex = new Integer(columnIndexProp);
}
//将该数据库列和java属性对应实例化一个ResultMapping添加到ResultMapConfig对象中
state.getResultConfig().addResultMapping(propertyName, columnName, columnIndex, javaClass, jdbcType, nullValue, notNullColumn, statementName, resultMapName, typeHandlerImpl);
}
});
//注册/sqlMap/resultMap/discriminator/subMap节点
parser.addNodelet("/sqlMap/resultMap/discriminator/subMap", new Nodelet() {
public void process(Node node) throws Exception {
Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
String value = childAttributes.getProperty("value");
String resultMap = childAttributes.getProperty("resultMap");
resultMap = state.applyNamespace(resultMap);
state.getResultConfig().addDiscriminatorSubMap(value, resultMap);
}
});
//注册/sqlMap/resultMap/discriminator节点
parser.addNodelet("/sqlMap/resultMap/discriminator", new Nodelet() {
public void process(Node node) throws Exception {
Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
String nullValue = childAttributes.getProperty("nullValue");
String jdbcType = childAttributes.getProperty("jdbcType");
String javaType = childAttributes.getProperty("javaType");
String columnName = childAttributes.getProperty("column");
String columnIndexProp = childAttributes.getProperty("columnIndex");
String callback = childAttributes.getProperty("typeHandler");
Class javaClass = null;
javaType = state.getConfig().getTypeHandlerFactory().resolveAlias(javaType);
if (javaType != null && javaType.length() > 0) {
javaClass = Resources.classForName(javaType);
}
Object typeHandlerImpl = null;
if (callback != null && callback.length() > 0) {
callback = state.getConfig().getTypeHandlerFactory().resolveAlias(callback);
typeHandlerImpl = Resources.instantiate(callback);
}
Integer columnIndex = null;
if (columnIndexProp != null) {
columnIndex = new Integer(columnIndexProp);
}
state.getResultConfig().setDiscriminator(columnName, columnIndex, javaClass, jdbcType, nullValue, typeHandlerImpl);
}
});
}
addStatementNodelets:
protected void addStatementNodelets() {
//注册/sqlMap/statement标签的解析处理
parser.addNodelet("/sqlMap/statement", new Nodelet() {
public void process(Node node) throws Exception {
statementParser.parseGeneralStatement(node, new MappedStatement());
}
});
//注册/sqlMap/insert标签的解析处理
parser.addNodelet("/sqlMap/insert", new Nodelet() {
public void process(Node node) throws Exception {
statementParser.parseGeneralStatement(node, new InsertStatement());
}
});
//注册/sqlMap/update标签的解析处理
parser.addNodelet("/sqlMap/update", new Nodelet() {
public void process(Node node) throws Exception {
statementParser.parseGeneralStatement(node, new UpdateStatement());
}
});
//注册/sqlMap/delete标签的解析处理
parser.addNodelet("/sqlMap/delete", new Nodelet() {
public void process(Node node) throws Exception {
statementParser.parseGeneralStatement(node, new DeleteStatement());
}
});
//注册/sqlMap/select标签的解析处理
parser.addNodelet("/sqlMap/select", new Nodelet() {
public void process(Node node) throws Exception {
statementParser.parseGeneralStatement(node, new SelectStatement());
}
});
//注册/sqlMap/procedure标签的解析处理
parser.addNodelet("/sqlMap/procedure", new Nodelet() {
public void process(Node node) throws Exception {
statementParser.parseGeneralStatement(node, new ProcedureStatement());
}
});
}
因为关于SQL
语句的解析都是交给com.ibatis.sqlmap.engine.builder.xml.SqlStatementParser#parseGeneralStatement
,所以我们来看下其内部实现:
public void parseGeneralStatement(Node node, MappedStatement statement) {
// 获取节点上的属性
Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
//语句id
String id = attributes.getProperty("id");
//参数集合名
String parameterMapName = state.applyNamespace(attributes.getProperty("parameterMap"));
//参数类名
String parameterClassName = attributes.getProperty("parameterClass");
//映射结果集名
String resultMapName = attributes.getProperty("resultMap");
//映射结果类名
String resultClassName = attributes.getProperty("resultClass");
//缓存名
String cacheModelName = state.applyNamespace(attributes.getProperty("cacheModel"));
String xmlResultName = attributes.getProperty("xmlResultName");
String resultSetType = attributes.getProperty("resultSetType");
String fetchSize = attributes.getProperty("fetchSize");
String allowRemapping = attributes.getProperty("remapResults");
//语句执行超时时间
String timeout = attributes.getProperty("timeout");
//是否使用了命名空间
if (state.isUseStatementNamespaces()) {
id = state.applyNamespace(id);
}
//处理结果集合名
String[] additionalResultMapNames = null;
if (resultMapName != null) {
additionalResultMapNames = state.getAllButFirstToken(resultMapName);
resultMapName = state.getFirstToken(resultMapName);
resultMapName = state.applyNamespace(resultMapName);
//处理多个的情况
for (int i = 0; i < additionalResultMapNames.length; i++) {
additionalResultMapNames[i] = state.applyNamespace(additionalResultMapNames[i]);
}
}
//处理结果类
String[] additionalResultClassNames = null;
if (resultClassName != null) {
additionalResultClassNames = state.getAllButFirstToken(resultClassName);
resultClassName = state.getFirstToken(resultClassName);
}
//处理多个的情况
Class[] additionalResultClasses = null;
if (additionalResultClassNames != null) {
additionalResultClasses = new Class[additionalResultClassNames.length];
for (int i = 0; i < additionalResultClassNames.length; i++) {
additionalResultClasses[i] = resolveClass(additionalResultClassNames[i]);
}
}
Class parameterClass = resolveClass(parameterClassName);
Class resultClass = resolveClass(resultClassName);
Integer timeoutInt = timeout == null ? null : new Integer(timeout);
Integer fetchSizeInt = fetchSize == null ? null : new Integer(fetchSize);
boolean allowRemappingBool = "true".equals(allowRemapping);
//实例化MappedStatementConfig对象
MappedStatementConfig statementConf = state.getConfig().newMappedStatementConfig(id, statement,
new XMLSqlSource(state, node), parameterMapName, parameterClass, resultMapName, additionalResultMapNames, resultClass, additionalResultClasses, resultSetType, fetchSizeInt, allowRemappingBool, timeoutInt, cacheModelName, xmlResultName);
findAndParseSelectKey(node, statementConf);
}
newMappedStatementConfig:
public MappedStatementConfig newMappedStatementConfig(String id, MappedStatement statement, SqlSource processor, String parameterMapName, Class parameterClass, String resultMapName, String[] additionalResultMapNames, Class resultClass, Class[] additionalResultClasses, String resultSetType, Integer fetchSize, boolean allowRemapping, Integer timeout, String cacheModelName, String xmlResultName) {
return new MappedStatementConfig(this, id, statement, processor, parameterMapName, parameterClass, resultMapName, additionalResultMapNames, resultClass, additionalResultClasses, cacheModelName, resultSetType, fetchSize, allowRemapping, timeout, defaultStatementTimeout, xmlResultName);
}
MappedStatementConfig构造函数:
MappedStatementConfig(SqlMapConfiguration config, String id, MappedStatement statement, SqlSource processor, String parameterMapName, Class parameterClass, String resultMapName, String[] additionalResultMapNames, Class resultClass, Class[] additionalResultClasses, String cacheModelName, String resultSetType, Integer fetchSize, boolean allowRemapping, Integer timeout, Integer defaultStatementTimeout, String xmlResultName) {
this.client = config.getClient();
SqlMapExecutorDelegate delegate = client.getDelegate();
this.typeHandlerFactory = config.getTypeHandlerFactory();
if (resultMapName != null) {
//根据结果集名获取结果集
statement.setResultMap(client.getDelegate().getResultMap(resultMapName));
//处理多个结果集的情况
if (additionalResultMapNames != null) {
for (int i = 0; i < additionalResultMapNames.length; i++) {
statement.addResultMap(client.getDelegate().getResultMap(additionalResultMapNames[i]));
}
}
}
//处理参数集合
if (parameterMapName != null) {
statement.setParameterMap(client.getDelegate().getParameterMap(parameterMapName));
}
//设置语句id
statement.setId(id);
statement.setResource(errorContext.getResource());
if (resultSetType != null) {
if ("FORWARD_ONLY".equals(resultSetType)) {
statement.setResultSetType(new Integer(ResultSet.TYPE_FORWARD_ONLY));
} else if ("SCROLL_INSENSITIVE".equals(resultSetType)) {
statement.setResultSetType(new Integer(ResultSet.TYPE_SCROLL_INSENSITIVE));
} else if ("SCROLL_SENSITIVE".equals(resultSetType)) {
statement.setResultSetType(new Integer(ResultSet.TYPE_SCROLL_SENSITIVE));
}
}
if (fetchSize != null) {
statement.setFetchSize(fetchSize);
}
// 从属性或映射设置参数类(确保匹配)
ParameterMap parameterMap = statement.getParameterMap();
if (parameterMap == null) {
statement.setParameterClass(parameterClass);
} else {
statement.setParameterClass(parameterMap.getParameterClass());
}
// 处理SQL语句,包括内联参数集合
Sql sql = processor.getSql();
setSqlForStatement(statement, sql);
// 设置空结果映射或自动结果映射
ResultMap resultMap = (ResultMap) statement.getResultMap();
if (resultMap == null && resultClass == null) {
statement.setResultMap(null);
} else if (resultMap == null) {
resultMap = buildAutoResultMap(allowRemapping, statement, resultClass, xmlResultName);
statement.setResultMap(resultMap);
if (additionalResultClasses != null) {
for (int i = 0; i < additionalResultClasses.length; i++) {
statement.addResultMap(buildAutoResultMap(allowRemapping, statement, additionalResultClasses[i], xmlResultName));
}
}
}
//设置执行语句超时时间
statement.setTimeout(defaultStatementTimeout);
if (timeout != null) {
statement.setTimeout(timeout);
}
//设置SqlMap客户端
statement.setSqlMapClient(client);
//如果有使用缓存则包装成CachingStatement
if (cacheModelName != null && cacheModelName.length() > 0 && client.getDelegate().isCacheModelsEnabled()) {
CacheModel cacheModel = client.getDelegate().getCacheModel(cacheModelName);
mappedStatement = new CachingStatement(statement, cacheModel);
} else {
mappedStatement = statement;
}
rootStatement = statement;
//将该语句添加到SqlMapExecutorDelegate的mappedStatements集合中
delegate.addMappedStatement(mappedStatement);
}
到此为止,关于sqlMap
节点的解析就完成了。
总结
sqlMap
节点的解析其实和sqlMapConfig.xml
配置文件差不多,都是注册对应的节点,然后进行解析。我们常用的SQL
语句分别使用select
、delete
、update
、insert
来进行处理,还有特殊的statement
和存储过程procedure
。将对应的语句进行解析然后拼凑成一个完整的MappedStatement
对象,然后放到SqlMapExecutorDelegate
对象的mappedStatements集合中。