【问题标题】:Does jOOQ support parsing of nested rows?jOOQ 是否支持解析嵌套行?
【发布时间】:2018-09-12 17:49:42
【问题描述】:

我正在评估我们是否可以为我们的项目从普通 JDBC 迁移到 jOOQ。其中大部分看起来很有希望,但我目前想知道一个特定的流程:嵌套行。让我解释一下。

假设你有以下两个表:

class(id, name)
student(id, name, class_id)

(我们假设一个学生只能是一个班级的一部分。)

让我们为这些表创建一个响应类型。我将在下面的查询中使用这些。

create type type_student as(id integer, name text);
create type type_class as(id integer, name text, students type_student[]);

现在让我们使用嵌套行获取所有类及其学生:

select row(class.id, class.name, array
       (
         select row(student.id, student.name)::type_student
         from   student
         where  student.class_id = class.id
       ))::type_class
from   class

一个有用的变体是只使用数组中的嵌套行:

select class.id, class.name, array
       (
         select row(student.id, student.name)::type_student
         from   student
         where  student.class_id = class.id
       ) as students
from   class

我想知道 jOOQ 是否有一种优雅的方法来解析包含嵌套行的此类结果?

【问题讨论】:

  • “解析”是什么意思?您是在谈论 jOOQ 解析器(例如通过此网站公开:jooq.org/translate),它将您的 SQL 字符串解析为 jOOQ 表达式树,或者您是在使用这个术语通俗地说“jOOQ 支持该功能”?
  • 嗨@LukasEder。我的措辞确实不是很清楚。我的意思是询问 jOOQ 是否支持以优雅的方式将这些结果解析为 POJO 模型。从使用 JDBC 的经验中,我了解到解析 row(...) 结果,尤其是嵌套的 row(...) 结果非常麻烦且令人沮丧。我想知道 jOOQ 提供了哪些功能来解析这些。所以关于你的问题,我问的是后者。我希望这有点道理。谢谢。
  • 哦,我明白了,“解析”就像“解析繁琐的 PostgreSQL 对象表示法”:-)

标签: sql postgresql jooq


【解决方案1】:

您对“parse”一词的使用可能意味着几件事,如果有人发现这个问题正在寻找“jOOQ”/“parse”/“row”,我会全部回答。

org.jooq.Parser 是否支持行值表达式?

还没有(从 jOOQ 3.10 和 3.11 开始)。 jOOQ 附带一个 SQL 解析器,它解析(几乎)任何可以使用 jOOQ API 表示的内容。这有很多好处,包括:

  • 能够对代码生成器的 DDL 脚本进行逆向工程
  • 在方言之间翻译 SQL(在此处查看在线版本:https://www.jooq.org/translate

不幸的是,它还不能解析投影中的行值表达式,即在SELECT 子句中。

jOOQ API 是否支持(“解析”)行值表达式?

是的,您可以使用各种DSL.row() 构造函数来使用它们,主要用于谓词,但也可以通过使用DSL.rowField() 将它们包装在Field 中来用于投影。从 jOOQ 3.11 开始,这仍然有点实验性,因为 PostgreSQL 本身有许多边缘案例,与允许的和不允许的有关。但原则上,像你这样的查询应该是可能的

jOOQ 是否支持解析 PostgreSQL 的序列化版本record

PostgreSQL 支持这些匿名的record 类型,以及命名的“复合”类型。及其数组。以及数组和复合类型的嵌套。如果类型信息可用于 jOOQ,即如果您使用代码生成器,jOOQ 可以序列化和反序列化这些类型。例如,如果您的查询存储为视图

create view test as
select row(class.id, class.name, array
       (
         select row(student.id, student.name)::type_student
         from   student
         where  student.class_id = class.id
       ))::type_class
from   class

然后,代码生成器会生成相应的类型,包括:

  • TypeStudentRecord
  • TypeClassRecord

可以按预期序列化。原则上,如果没有代码生成器,这也是可能的,但是您必须自己手动创建上述类型,所以为什么不直接使用代码生成器。

【讨论】:

  • 我对迟到的回复表示歉意。谢谢,非常有用的见解。
【解决方案2】:

是的:https://www.jooq.org/doc/latest/manual/sql-building/table-expressions/nested-selects/

Field<Object> records =
create.select(student.id, student.name)
      .from(student)
      .where(student.class_id.eq(class.id)
      .asField("students");

create.select(class.id, class.name, array, records)
      .from(class)
      .fetch();

上面的例子可能不能直接工作,因为我没有尝试过,只是想给出一个大概的想法。

注意:对象记录不是单独执行的。当在第二条语句中调用fetch 时,JOOQ 应该在内部创建一条 SQL 语句。

【讨论】:

  • 谢谢。尽管这并不能真正回答我的问题(请参阅上面的评论),但我非常感谢您的努力和解释。不过,这并没有使用row(...) 构建学生记录。
  • 你是这个意思吗? jooq.org/javadoc/3.3.0/org/jooq/DSLContext.html 有一个名为 selectFrom(TABLE_NAME) 的命令替换了 select(student.id, student.name) 以返回整行
猜你喜欢
  • 2016-11-06
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-07
  • 2015-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多