统一的一个接口:sqlSource
俩个实现类:
1.RawSqlSource
解析:select * from user where name = #{name}
属性字段 sqlSource --StaticSqlSource类型的
StaticSqlSource进行将'#{}'替换为 ?占位符
StaticSqlSource中的属性字段sql用于存储解析后的sql
select * from user where name = ?
2.DynamicSqlSource
解析含有 '${}'或 <where>,<if>等标签的sql
select * from ${tablename} where name = #{name}
insert into u_user(usercode,username,createtime,usertype,mobile)
values
<foreach collection="list" item="user" separator=",">
(#{user.userCode},#{user.userName}
,#{user.createTime},#{user.userType},#{user.mobile})
</foreach>
啥时候解析生成sql,在getBoundSql()方法中,解析动态sql,最终
解析后结果
select * from user where name = ?
insert into u_user(usercode,username,createtime,usertype,mobile)
values
(?,?
,?,?,?)
,
(?,?
,?,?,?)
//XMLStatementBuilder类,解析某个sql 如:<select>....</select>
public void parseStatementNode() {
//省略
//我们主要看这一行代码
SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
// 省略
}
先说结论:什么时候我们的SqlSource用DynamicSqlSource?只要我们含有 元素节点(比如:<if>,<where>)或者我们的文本中含有 '${}'时,我们就使用动态的sqlSource。
//默认的用这个驱动,当然这儿我们可以通过配置,使用别的驱动来解析xml
// XMLLanguageDriver类
@Override
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
return builder.parseScriptNode();
}
/**
context的内容如下:
<select resultType="learn.User" parameterType="String" id="selectUserByIdFromTable">
select * from ${tableName} where usercode = #{id}
</select>
*/
public SqlSource parseScriptNode() {
//重点看这一行代码,里面负责给isDynamic赋值
MixedSqlNode rootSqlNode = parseDynamicTags(context);
SqlSource sqlSource;
if (isDynamic) {
sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
} else {
sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
}
return sqlSource;
}
protected MixedSqlNode parseDynamicTags(XNode node) {
//用于解析某一个sql语句 如: <select>....</select>
List<SqlNode> contents = new ArrayList<>();
NodeList children = node.getNode().getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
XNode child = node.newXNode(children.item(i));
if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
// 这是解析xml文档中的文本。比如 我们的
// select * from ${tableName} where usercode = #{id}
String data = child.getStringBody("");
TextSqlNode textSqlNode = new TextSqlNode(data);
if (textSqlNode.isDynamic()) {//这个方法用于判断我们的sql文本是否是动态的sql,
// 只要有 ‘${}’存在,就是动态sql
conte