Mybatis框架中的foreach标签解析

news/2025/2/1 20:51:13 标签: mybatis, java, foreach

如果是foreachNode则会预填充很多的参数及SQL语句以及展开的参数信息。foreach标签的注册:

当出现foreach标签的时候则调用对应的处理函数:

java">private void initNodeHandlerMap() {
        nodeHandlerMap.put("if", new IfHandler());
        nodeHandlerMap.put("foreach", new ForeachHandler());
    }

处理函数初始化foreach节点配置属性:

java">        @Override
        public void handleNode(XNode var1, List<SqlNode> var2) {
            MixedSqlNode mixedSqlNode = new MixedSqlNode(parseDynamicTags(var1));
            String collection = var1.getStringAttribute("collection");
            String item = var1.getStringAttribute("item");
            String index = var1.getStringAttribute("index");
            String open = var1.getStringAttribute("open");
            String close = var1.getStringAttribute("close");
            String separator = var1.getStringAttribute("separator");
            ForEachSqlNode foreachSqlNode = new ForEachSqlNode(XMLScriptBuilder.this.configuration,mixedSqlNode, collection, index, item, open, close, separator);
            var2.add(foreachSqlNode);
        }

这样就完成foreach标签的初始化,当系统执行的时候就需要组装SQL语句信息,这里还是apply方法,其中参数为传入的上下文信息。执行的原理就是:

  1. 通过ognl计算器获取遍历的集合对象;
  2. 根据open,close配置属性在sql中填充值;
  3. 在解析参数过程中最重要的就是对填充的每个item如何赋值?这里通过将配置的index和item都传入到DynamicContext中,这里的DynamicContext作用类似于符号表,用于保存执行上下文的变量配置信息,其中item生成的临时变量格式为: "__frch_" + item + "_" + I,index值为map中的key或者遍历的次数。
  4. 系统通过这些上下文最终执行foreach标签中的对象,产生sql语句,执行完成后移除这些临时生成的上下文信息。

在第三步中,为了方便将产生的临时变量替换为用户定义的值,这里进行了替换:

java"> public void appendSql(String sql) {
            GenericTokenParser parser = new GenericTokenParser("#{", "}", (content) -> {
                String newContent = content.replaceFirst("^\\s*" + this.item + "(?![^.,:\\s])", ForEachSqlNode.itemizeItem(this.item, this.index));
                if (this.itemIndex != null && newContent.equals(content)) {
                    newContent = content.replaceFirst("^\\s*" + this.itemIndex + "(?![^.,:\\s])", ForEachSqlNode.itemizeItem(this.itemIndex, this.index));
                }

                return "#{" + newContent + "}";
            });
            this.delegate.appendSql(parser.parse(sql));
        }

因为用户上下文(符号表)更新了,所以这里相应进行了处理。

java">@Override
    public boolean apply(DynamicContext context) {
        Map<String, Object> bindings = context.bindingsAsMap();
        Iterable<?> iterable = ForEachSqlNode.this.evaluator.evaluateIterable(collectionExpression, bindings);
        if(!iterable.iterator().hasNext()) {
            return true;
        } else {
            boolean first = true;
            this.applyOpen(context);
            int i = 0;
            for(Object o:iterable) {
                if(!first && this.separator != null) {
                    context = new PrefixedContext(context, this.separator);
                } else {
                    context = new PrefixedContext(context, "");
                }
                int uniqueNumber = context.getUniqueNumber();
                if(o instanceof  Map.Entry) {
                    Map.Entry<Object, Object> entry = (Map.Entry)o;
					//这里将index和item都添加到符号表中
                    this.applyIndex(context, entry.getKey(), uniqueNumber);
                    this.applyItem(context, entry.getValue(), uniqueNumber);
                } else {
//这里将index和item都添加到符号表中
                    this.applyIndex(context, i, uniqueNumber);
                    this.applyItem(context, o, uniqueNumber);
                }
                this.contents.apply(new FilteredDynamicContext(this.configuration, context, this.index, this.item, uniqueNumber));
                if(first) {
                    first = !((PrefixedContext)context).isPrefixApplied();
                }
                context = ((PrefixedContext) context).delegate;
                ++i;
            }
            this.applyClose(context);
            context.getBindings().remove(this.item);
            context.getBindings().remove(this.index);
            return true;
        }
    }

http://www.niftyadmin.cn/n/5839572.html

相关文章

【毕业与课程大作业参考】基于 yolov8+pyqt5 界面自适应的表情识别检测系统 demo

【毕业与课程大作业参考】基于yolov8pyqt5界面自适应的表情识别检测系统demo.zip资源-CSDN文库 【毕业与课程大作业参考】基于 yolov8pyqt5 界面自适应的表情识别检测系统 demo 在人工智能和计算机视觉领域&#xff0c;表情识别检测系统是一个极具趣味性和挑战性的项目。对于正…

【TOGAF系列】ADF技术第五章:差距分析

被称为差距分析的技术在TOGAF架构开发方法&#xff08;ADM&#xff09;中被广泛用于验证正在开发的架构。基本前提是强调基线架构和目标架构之间的不足&#xff1b;也就是说&#xff0c;被故意省略、意外遗漏或尚未定义的项目。 5.1 介绍 验证架构的一个关键步骤是考虑可能被…

【Rust自学】17.2. 使用trait对象来存储不同值的类型

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 17.2.1. 需求 这篇文章以一个例子来介绍如何在Rust中使用trait对象来存储不同值的类型。 …

研发的护城河到底是什么?

0 你的问题&#xff0c;我知道&#xff01; 和大厂朋友聊天&#xff0c;他感叹原来努力干活&#xff0c;做靠谱研发&#xff0c;积累职场经验&#xff0c;干下来&#xff0c;职业发展一般问题不大。而如今大厂“年轻化”&#xff0c;靠谱再不能为自己续航&#xff0c;企业似乎…

Python GIL(全局解释器锁)机制对多线程性能影响的深度分析

在Python开发领域&#xff0c;GIL&#xff08;Global Interpreter Lock&#xff09;一直是一个广受关注的技术话题。在3.13已经默认将GIL去除&#xff0c;在详细介绍3.13的更亲前&#xff0c;我们先要留了解GIL的技术本质、其对Python程序性能的影响。本文将主要基于CPython&am…

向上调整算法(详解)c++

算法流程&#xff1a; 与⽗结点的权值作⽐较&#xff0c;如果⽐它⼤&#xff0c;就与⽗亲交换&#xff1b; 交换完之后&#xff0c;重复 1 操作&#xff0c;直到⽐⽗亲⼩&#xff0c;或者换到根节点的位置 这里为什么插入85完后合法&#xff1f; 我们插入一个85&#xff0c;…

IT运维的365天--025 H3C交换机用NTP同步正确的时间

前情提要&#xff1a;网络设备基本也都是有自己的时间的&#xff0c;如果时间不正确&#xff0c;别扭不说&#xff0c;查日志肯定就很不方便了&#xff0c;还有就是怕某些特别的应用会出错&#xff08;概率很低&#xff09;。所以&#xff0c;虽然好久都没事&#xff0c;但强迫…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.28 存储之道:跨平台数据持久化方案

好的&#xff0c;我将按照您的要求生成一篇高质量的Python NumPy文章。以下是第28篇《存储之道&#xff1a;跨平台数据持久化方案》的完整内容&#xff0c;包括目录、正文和参考文献。 1.28 存储之道&#xff1a;跨平台数据持久化方案 目录 #mermaid-svg-n1z37AP8obEgptkD {f…