Это не работает, потому что элемент 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>
Вам необходимо настроить проект, чтобы сделать скорость доступной.
Недостатком является то, что вы не можете связывать параметры с помощью подготовленного оператора (примечание 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;
}