解析<sql>
节点
在映射配置文件中,可以使用<sql>
节点定义可重用的~语句片段。当需要重用<sql>
节点中定义的SQL
语句片段时,只需要使用include节点引用相应的片段即可,这样,在编写SQL
语句以及维护这些SQL
语句时,都会比较方便。<include>
节点的解析在后面详细介绍。
XMLMapperBuilder.sqlElement()
方法负责解析映射配置文件中定义的的全部<sql>
节点,具体代码如下所示:
private void sqlElement(List<XNode> list, String requiredDatabaseId) {
//遍历所有的<sql>节点
for (XNode context : list) {
//解析<sql>节点
//获取<sql>节点的databaseId属性的值
String databaseId = context.getStringAttribute("databaseId");
//获取<sql>节点的id属性的值
String id = context.getStringAttribute("id");
//获取在当前命名空间的对应的全路径id
id = builderAssistant.applyCurrentNamespace(id, false);
//进行数据库ID匹配,如果当前sql片段所属的databaseId和configuration.databaseId相等
if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
//将匹配的sql片段,放入Configuration.sqlFragments集合中
sqlFragments.put(id, context);
}
}
}
这个章节比较简单,所以这里讲一下Configuration.StricMap
类:
这个类在存储解析Mapper
映射配置文件中之后的对象中,起到了至关重要的作用,具体体现如下所示:
/**
* key = Cache的ID (默认是映射文件的namespace)
* value = Cache对象(二级缓存)
*/
protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");
/**
* 用于存储ResultMap
*/
protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
/**
* 用于存储KeyGenerator
*/
protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<>("Key Generators collection");
/**
* 用于存储sql片段
*/
protected final Map<String, XNode> sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers");
为什么要使用StricMap
完成以上信息的存储,那取决于StricMap
的put()
方法的一些特性,具体如下所示:
public V put(String key, V value) {
//如果检测到重复的key直接抛出异常
if (containsKey(key)) {
throw new IllegalArgumentException(name + " already contains value for " + key
+ (conflictMessageProducer == null ? "" : conflictMessageProducer.apply(super.get(key), value)));
}
//如果没有重复的key则添加key以及value
//同时根据key产生shortKey
if (key.contains(".")) {
//按照“.”将key切分成数组,然后将数组的最后一项作为shortKey
final String shortKey = getShortName(key);
//如果不包含指定shortKey,则添加该键值对
if (super.get(shortKey) == null) {
super.put(shortKey, value);
} else {
//如果该shortKey已经存在,则将value修改成Ambiguity对象
super.put(shortKey, (V) new Ambiguity(shortKey));
}
}
//如果没有重复的key则添加key以及value(这是全面)
return super.put(key, value);
}
在调用StricMap.put()
方法的时候,首先要检查key
是否存在,如果存在会直接报错。
那么为什么在检查key
存在之后就直接报错呢?原因如下所示:
传入的
key
等于调用builderAssistant.applyCurrentNamespace(id, false)
返回的值,在调用builderAssistant.applyCurrentNamespace()
方法参入的id
是节点的id
,例如:whereSqlElement
就是传入的id
值。<sql id="whereSqlElement"> where blog_id = ${idValue} </sql>
因为同一个
Mapper.xml
中,不用有id
相同的标签,如上代码块,而万一Mapper
配置文件中真的有两段一样的代码,就应该提前报错告诉开发人员去更改,所以StricMap.put()
中的首先检测key
是否存在,不存在就直接报错。StricMap.put()
会向集合中加入两条数据,一条是全名key
,一条是shorKey
名。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!