当前位置: 首页 > 知识库问答 >
问题:

如何使用JOOQ递归地获取自引用表的父/子?

空英达
2023-03-14

我想使用JOOQ递归地获取自引用表的父级和子级。

目标是直接在POJO中获取。

我没有在JOOQ留档或其他任何地方找到任何这样的例子,但我认为结合多集和递归JOOQ方法是可能的。https://www.jooq.org/doc/3.14/manual/sql-building/sql-statements/with-recursive-clause/https://www.jooq.org/doc/latest/manual/sql-building/column-expressions/multiset-value-constructor/

到目前为止,我的问题和我所做的细节(我在这里简化了表格和对象):

自引用表视图项:

POJO:

public class ViewItem {
  private final String id;
  private final List<ViewItem> childrens;

  public ViewItem(final String id) {
    this.id = id;
    this.childrens = new ArrayList<>();
  }

  public Integer getId() {
    return id;
  }

  public void addChild(final ViewItem child) {
    this.childrens.add(child);
  }

  public List<ViewItem> getChildrens() {
    return childrens;
  }

}

用JOOQ选择:

  public List<ViewItem> getViewItems(final String viewId) throws IOException {
    final CommonTableExpression<?> cte = DSL.name("t")
        .as(DSL
            .select(Tables.VIEW_ITEM.ID, Tables.VIEW_ITEM.PARENT_ID,
                DSL.multiset(DSL.select().from(DSL.table("t")).join(Tables.VIEW_ITEM)
                    .on((DSL.field(DSL.name("t", "parent_id")))
                        .eq(Tables.VIEW_ITEM.ID)))
                    .as("childrens"))
            .from(Tables.VIEW_ITEM).where(Tables.VIEW_ITEM.ID.eq(viewItemId)));
    final List<ViewItem> items =
        dslContext.withRecursive(cte).selectFrom(cte).fetch().into(ViewItem.class);
    return items;
  }

但在运行查询时接收堆栈以下跟踪:

org.jooq.exception.DataAccessException: SQL [set @t = @@group_concat_max_len; set @@group_concat_max_len = 4294967295; with recursive `t2` as (select `tedcvsrepo`.`view_item`.`sort_order`, `tedcvsrepo`.`view_item`.`structure_id`, `tedcvsrepo`.`view_item`.`template_id`, `tedcvsrepo`.`view_item`.`parent_structure_id`, `tedcvsrepo`.`view_item`.`template`, `tedcvsrepo`.`view_item`.`draft`, `tedcvsrepo`.`view_item`.`draft_reason`, (select coalesce(json_merge_preserve('[]', concat('[', group_concat(json_array() separator ','), ']')), json_array()) from (select * from t2 join `tedcvsrepo`.`view_item` on `t2`.`parent_structure_id` = `tedcvsrepo`.`view_item`.`structure_id`) as `t`) as `childrens` from `tedcvsrepo`.`view_item` where (`tedcvsrepo`.`view_item`.`view_id` = ? and `tedcvsrepo`.`view_item`.`parent_structure_id` = ?) order by `tedcvsrepo`.`view_item`.`sort_order` asc) select `t2`.`sort_order`, `t2`.`structure_id`, `t2`.`template_id`, `t2`.`parent_structure_id`, `t2`.`template`, `t2`.`draft`, `t2`.`draft_reason`, `t2`.`childrens` from `t2`; set @@group_concat_max_len = @t;]; In recursive query block of Recursive Common Table Expression 't2', the recursive table must be referenced only once, and not in any subquery
    at org.jooq_3.16.5.MYSQL.debug(Unknown Source)
    at org.jooq.impl.Tools.translate(Tools.java:3102)
    at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:670)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:354)
    at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:284)
    at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2843)
    at eu.europa.ec.mdm.repository.ViewRepository.getViewMultiselect(ViewRepository.java:116)
    at eu.europa.ec.mdm.repository.ViewRepository$$FastClassBySpringCGLIB$$99dace9d.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at eu.europa.ec.mdm.repository.ViewRepository$$EnhancerBySpringCGLIB$$80c1116d.getViewMultiselect(<generated>)
    at eu.europa.ec.mdm.repository.ViewRepositoryIt.getViewMultiselectTest(ViewRepositoryIt.java:33)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:95)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:91)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:60)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.sql.SQLException: In recursive query block of Recursive Common Table Expression 't2', the recursive table must be referenced only once, and not in any subquery
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
    at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:371)
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
    at org.jooq.tools.jdbc.DefaultPreparedStatement.execute(DefaultPreparedStatement.java:219)
    at org.jooq.impl.Tools.executeStatementAndGetFirstResultSet(Tools.java:4327)
    at org.jooq.impl.AbstractResultQuery.execute(AbstractResultQuery.java:230)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:340)
    ... 83 more

我是做错了什么,还是根本没有办法实现我想用JOOQ做的事情?

共有1个答案

陆安国
2023-03-14

您的问题非常相似,但与此不完全相同:从Postgres和jOOQ中的分层表递归生成JSON树

这个问题没有一个非常方便的jOOQ答案,它在PostgreSQL上只使用SQL/JSON,这在递归方面比MySQL更强大。在jOOQ中完全使用递归和多重集将非常困难。也许,只需以平面格式获取数据,然后将其组装到实用程序中?

有一个功能请求可以帮助您在jOOQ中开箱即用,但对于jOOQ 3.17,考虑到复杂性,它还不是优先事项:https://github.com/jOOQ/jOOQ/issues/12341

 类似资料:
  • 问题内容: 使用MySQL,我想从具有此类字段结构的表中返回父母列表。ID,PARENTID,NAME(标准的父子层次结构)。我想遍历树以返回所有“父母”的列表。 我意识到“嵌套集”可能是处理此问题的更好方法-但目前我无法更改数据的结构。我将来会希望这样做。当前-我的数据集实际上将包含一些深度级别- 没什么疯狂的……也许2-5,所以我的递归命中不应太“昂贵”。 我已经看过SQL Server获取父

  • 问题内容: 我的数据库看起来像(pligg cms,样本数据) 假设,如何获取芝加哥的顶级parentID,它应该是位置。 我是否在php中编写了递归函数,或者在mysql中可行? 问题答案: 该网站非常好地概述了在mysql和PHP中存储分层数据的不同方法。要回答您的问题,最简单的方法是使用php和递归。您可以使用其他方法,例如,不需要多个数据库查询。但是,在处理大量插入和更新时,此方法的实现可

  • 我一直在使用模式。方法来获取模式中的表列表,但今天我发现该方法返回的是执行jOOQ代码生成时存在的表列表,而不是此时存在的表。 我的具体用例是随着时间的推移创建表(自动分区),我们的Java服务对它们执行一些操作。 在jOOQ中有没有办法从DB中获取当前的表列表? 我可以求助于查询信息模式。直接使用表,但我更愿意重用来自jOOQ的方法(如果可用的话)。

  • 问题内容: 我有这个小问题。 该表基本上如下所示 学科 SubjectId SubjectName ParentSubjectId 引用主题表本身。并且可以下降很多级别(没有特定数量的级别) 示例(仅出于示例目的,使用国家/地区): 等等.. SubjectID是GUID ParentSubjectID也是GUID。 样本概述:http : //i.imgur.com/a2u2CfT.png 它甚

  • 问题内容: 嗨,我有一个引用自己的表,我需要能够从给定的父ID中选择父及其所有子记录。 我的表如下: 因此,对于上面的示例,我希望能够传递值1并获取上面的所有记录。 到目前为止,我已经提出了以下递归表值函数,但是它的行为不符合预期(仅返回第一条记录)。 问题答案: 你可以试试这个

  • 我有内部节点和终端节点的树状结构: 我现在有一个