聊聊Mybatis的动态Sql之这三个SqlNode同样重要
Posted 周杰伦本人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊Mybatis的动态Sql之这三个SqlNode同样重要相关的知识,希望对你有一定的参考价值。
@[TOC]
聊聊Mybatis的动态Sql之这三个SqlNode同样重要
ForEachSqlNode
ForEachSqlNode是解析出<foreach>
的对象,
@Override
public boolean apply(DynamicContext context)
Map<String, Object> bindings = context.getBindings();
final Iterable<?> iterable = evaluator.evaluateIterable(collectionExpression, bindings,
Optional.ofNullable(nullable).orElseGet(configuration::isNullableOnForEach));
if (iterable == null || !iterable.iterator().hasNext())
return true;
boolean first = true;
applyOpen(context);
int i = 0;
for (Object o : iterable)
DynamicContext oldContext = context;
if (first || separator == null)
context = new PrefixedContext(context, "");
else
context = new PrefixedContext(context, separator);
int uniqueNumber = context.getUniqueNumber();
// Issue #709
if (o instanceof Map.Entry)
@SuppressWarnings("unchecked")
Map.Entry<Object, Object> mapEntry = (Map.Entry<Object, Object>) o;
applyIndex(context, mapEntry.getKey(), uniqueNumber);
applyItem(context, mapEntry.getValue(), uniqueNumber);
else
applyIndex(context, i, uniqueNumber);
applyItem(context, o, uniqueNumber);
contents.apply(new FilteredDynamicContext(configuration, context, index, item, uniqueNumber));
if (first)
first = !((PrefixedContext) context).isPrefixApplied();
context = oldContext;
i++;
applyClose(context);
context.getBindings().remove(item);
context.getBindings().remove(index);
return true;
- 解析<foreach> 的collection属性的表达式,得到集合,添加open属性的字符串
- 遍历集合,构建PrefixedContext对象,如果是Map类型,将key value保存到PrefixedContext对象中,不是的话就将集合元素下标志和集合元素保存到PrefixedContext对象中,调用SqlNode的apply()方法,处理#占位符
- 调用applyClose()方法添加close属性后缀
- 删除DynamicContext对象中的index和item
VarDeclSqlNode
VarDeclSqlNode是解析<bind>标签的类
public class VarDeclSqlNode implements SqlNode
private final String name;
private final String expression;
public VarDeclSqlNode(String var, String exp)
name = var;
expression = exp;
@Override
public boolean apply(DynamicContext context)
final Object value = OgnlCache.getValue(expression, context.getBindings());
context.bind(name, value);
return true;
name保存了bind标签的name属性值,value保存bind标签的value属性值,apply()方法中利用OGNL解析表达式的值,然后把name和value绑定到DynamicContext中,这样就能根据name获取到value值了。
ChooseSqlNode
ChooseSqlNode是解析出choose标签的类
public class ChooseSqlNode implements SqlNode
private final SqlNode defaultSqlNode;
private final List<SqlNode> ifSqlNodes;
public ChooseSqlNode(List<SqlNode> ifSqlNodes, SqlNode defaultSqlNode)
this.ifSqlNodes = ifSqlNodes;
this.defaultSqlNode = defaultSqlNode;
@Override
public boolean apply(DynamicContext context)
for (SqlNode sqlNode : ifSqlNodes)
if (sqlNode.apply(context))
return true;
if (defaultSqlNode != null)
defaultSqlNode.apply(context);
return true;
return false;
它的apply()方法也比较简单:遍历所有ifSqlNodes,也是when标签的对象信息,调用各自的apply()方法,返回成功表示when条件成立,就返回true,defaultSqlNode不为空也是true,其他为false
总结
这篇文章主要讲了解析foreach标签的类ForEachSqlNode、解析<bind>标签的VarDeclSqlNode类和解析choose标签的ChooseSqlNode类,同时介绍这三个类的apply()方法的实现,这三个类都是SqlNode的实现类,都是对xml文件中的标签解析成的对象,这些SqlNode对象会被解析处理成SqlSource接口和它的实现类,供数据库执行,下篇文章我们将介绍SqlSource接口和它的实现类
以上是关于聊聊Mybatis的动态Sql之这三个SqlNode同样重要的主要内容,如果未能解决你的问题,请参考以下文章
聊聊Mybatis的BaseStatementHandler的三个子类
聊聊Mybatis的StatementHandler接口和它的实现类