聊聊Mybatis的动态Sql之这三个SqlNode同样重要
ForEachSqlNode
ForEachSqlNode是解析出
@Override
public boolean apply(DynamicContext context) {
Map 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
解析
遍历集合,构建PrefixedContext对象,如果是Map类型,将key value保存到PrefixedContext对象中,不是的话就将集合元素下标志和集合元素保存到PrefixedContext对象中,调用SqlNode的apply()方法,处理#{}占位符
调用applyClose()方法添加close属性后缀
删除DynamicContext对象中的index和item
VarDeclSqlNode
VarDeclSqlNode是解析
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 ifSqlNodes;
public ChooseSqlNode(List 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、解析
对文章中内容感兴趣的小伙伴可以搜索微信公众号:敲代码的老贾,领取相应资料