这是一个实验性功能,因此可能会发生变化。使用风险自负!
遍历
适用于 ❌ 开源版 ✅ 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 模板。另请参阅 需要代码生成的功能 以获取更多详细信息。
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!