这是一个实验性功能,因此可能会发生变化。使用风险自负!
遍历
适用于 ❌ 开源版 ✅ Express 版 ✅ 专业版 ✅ 企业版
虽然来自模型 API 的 访问器方法允许手动遍历表达式树,但遍历表达式树的更通用方法是使用 org.jooq.Traverser API,它可以以类似于 java.util.stream.Collector 迭代 java.util.stream.Stream 的方式遍历 org.jooq.QueryPart,收集和聚合有关表达式树的数据。一个 Traverser 包含此 API
public interface Traverser<A, R> {
/**
* A supplier for a temporary data structure to accumulate {@link QueryPart}
* objects into during traversal.
*/
Supplier<A> supplier();
/**
* An optional traversal abort condition to short circuit traversal e.g.
* when the searched object has been found.
*/
Predicate<A> abort();
/**
* An optional recursion condition to prevent entering a specific
* {@link QueryPart}, e.g. when it is undesired to enter any subqueries.
*/
Predicate<QueryPart> recurse();
/**
* An optional recursion condition to prevent entering a specific
* {@link QueryPart}'s children, e.g. when it is desired to traverse only
* into certain operators.
*/
Predicate<QueryPart> recurseChildren();
/**
* A callback that is invoked before recursing into a subtree.
*/
BiFunction<A, QueryPart, A> before();
/**
* A callback that is invoked after recursing into a subtree.
*/
BiFunction<A, QueryPart, A> after();
/**
* An optional transformation function to turn the temporary data structure
* supplied by {@link #supplier()} into the final data structure.
*/
Function<A, R> finisher();
}
一些元素类似于 java.util.stream.Collector,其他元素特定于树遍历。
一个简单的例子展示了可以做什么
// Any ordinary QueryPart:
Condition condition = BOOK.ID.eq(1);
int count = condition.$traverse(
// Supplier of the initial data structure: an int
() -> 0,
// Print all traversed QueryParts and increment the counter
(r, q) -> {
System.out.println("Part " + r + ": " + q);
return r + 1;
}
);
System.out.println("Count : " + count);
以上代码将打印
Part 0: "BOOK"."ID" = 1 Part 1: "BOOK"."ID" Part 2: 1 Count : 3
在稍微复杂的 QueryPart 上使用相同的 traverser
Condition condition = BOOK.ID.eq(1).or(BOOK.ID.eq(2)); // ...
Part 0: ("BOOK"."ID" = 1 or "BOOK"."ID" = 2)
Part 1: "BOOK"."ID" = 1
Part 2: "BOOK"."ID"
Part 3: 1
Part 4: "BOOK"."ID" = 2
Part 5: "BOOK"."ID"
Part 6: 2
Count : 7
重用你的 JDK collectors
任何 Collector 都可以使用 Traversers.collecting(Collector) 转换为 Traverser。例如,如果你想计算表达式中所有 QueryPart 项的数量,而不是上面手写的 traverser,只需使用 JDK Collectors.counting()
// Contains 3 query parts
long count1 = BOOK.ID.eq(1)
.$traverse(Traversers.collecting(Collectors.counting());
// Contains 7 query parts
long count2 = BOOK.ID.eq(1).or(BOOK.ID.eq(2))
.$traverse(Traversers.collecting(Collectors.counting());
限制
就像 模型 API 替换一样,traversers 不能遍历到“opaque” org.jooq.QueryPart 实例,包括 自定义 QueryParts 或 plain SQL 模板。另请参阅 需要代码生成的功能 以获取更多详细信息。
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!