gpt4 book ai didi

java - Mybatis SQL 中的递归导致编译时堆栈溢出

转载 作者:行者123 更新时间:2023-12-02 10:17:52 25 4
gpt4 key购买 nike

我有一个具有如下递归关系的类。

   Class A{
String id;
String op;
String val;
List<A> aList;
}

我正在使用 MySQL MyBatis 生成如下查询。


<sql id="testRecursion">
<foreach collection="A.aList" item="aList" open="(" separator=" UNION " close=")">
<if test="aList.op == null">
(
SELECT sum(val) as val FROM
FROM test_data
WHERE id = #{aList.id}
)
</if>

<if test="aList.op== 'AND'">
SELECT max(val) as val FROM
<include refid="testRecursion"/>
</if>

<if test="aList.op== 'OR'">
SELECT min(val) as val FROM
<include refid="testRecursion"/>
</if>
</foreach>
</sql>

在编译时出现以下错误,并出现堆栈溢出异常。

at org.apache.ibatis.builder.xml.XMLIncludeTransformer.applyIncludes(XMLIncludeTransformer.java:74) ~[mybatis-3.4.5.jar:3.4.5]
at org.apache.ibatis.builder.xml.XMLIncludeTransformer.applyIncludes(XMLIncludeTransformer.java:62) ~[mybatis-3.4.5.jar:3.4.5]

有人可以帮我看看如何在mybatis中实现递归吗?

最佳答案

这不起作用,因为 include 元素不支持递归,即您不能包含自身的 sql 代码段。

如果您切换到速度脚本引擎,您可以使用允许引用自身的宏来实现您需要的内容。

不幸的是,您尚未提供代码片段的调用代码,因此我的示例可能略有不同,您需要对其进行调整,但它应该可以为您提供想法。

给出 A 的定义:

public class A {
Integer id;
String op;
Integer val;
List<A> nodes;
// setters/getters omitted for brevity

您可以像这样定义映射器:

class MyMapper {
Integer getRecursive(@Param("A") A a);
}

并在 xml 中查询:

<select id="getRecursive" lang="velocity" resultType="int">
#macro(node $a)
#if( ! $a.op )
SELECT sum(val) as val FROM A
WHERE id = ${a.id}
#else
SELECT
#if( $a.op == "AND" )
max(val) as val
#else
min(val) as val
#end
FROM (
#repeat( $a.nodes $aNode "UNION ALL" )
#node($aNode)
#end
)
#end
#end

select val FROM (
#node($_parameter.A)
)
</select>

您需要configure该项目旨在提供速度。

缺点是您无法通过准备好的语句绑定(bind)参数(注意 id = ${a.id} 而不是 id = @{a.id} )。

这是我调用映射器方法的方法:

@Test
public void testRecursive() {
A a = or(leaf(1), and(leaf(2), leaf(3)));
assertThat(sut.getRecursive(a), equalTo(1));
}

private A leaf(int id) {
A a = new A();
a.setId(id);
return a;
}

private A or(A ... ops) {
return operation("OR", ops);
}

private A and(A ... ops) {
return operation("AND", ops);
}

private A operation(String operation, A ... ops) {
A a = new A();
a.setOp(operation);
a.setNodes(Arrays.asList(ops));
return a;
}

关于java - Mybatis SQL 中的递归导致编译时堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54545075/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com