jOOQ-使用嵌套子查询联接

时间:2019-03-19 10:22:15

标签: java sql jooq nested-query

比方说,我想找出谁在书本db(表CLRSBOOK和联结表AUTHOR)中写了BOOK_AUTHOR

SelectConditionStep<Record1<String>> query = create
        .select(AUTHOR.LASTNAME.as("AuthorName"))
            .from(
                    (
                            BOOK.leftOuterJoin(BOOK_AUTHOR).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
                    ).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
            )
            .where(BOOK.TITLE.eq(CLRS_title))
        ;

仅选择一本书就无法匹配整个桌子。我现在想在比赛之前选择那本书。

The jOOQ doc on this matter使我相信它看起来可能像这样:

Table<Record1<Integer>> clrs = create
        .select(BOOK.ID.as("bookID"))
            .from(BOOK)
            .where(BOOK.TITLE.eq(CLRS_title))

        .asTable()
        ;

SelectJoinStep<Record1<String>> query = create
        .select(AUTHOR.LASTNAME.as("AuthorName"))
            .from(
                    (
                            clrs.leftOuterJoin(BOOK_AUTHOR).on(clrs.field("bookID").eq(BOOK_AUTHOR.BOOKID))
                    ).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
            )
        ;

但是,由于

导致编译失败
Cannot resolve method 'eq(org.jooq.TableField<ch.cypherk.bookdb.public_.tables.records.BookAuthorRecord,java.lang.Integer>)'

处于连接条件。

编写此联接的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

您遇到的问题

您正在使用Table.field(String)从派生表中取消引用列:

clrs.field("bookID")

您要返回的类型是Field<?>,带有通配符。与任何通用类型一样,一旦有了通配符,该类型就将无法进行很多操作(但不是全部)。以List<?>为例。您仍然可以调用List<?>.get()来检索Object,但不能调用List<?>.add(? element)。在Field<?>中,除非将参数强制转换为原始类型,否则无法再调用eq()

您还可以将字段的<T>类型强制为您已经知道的类型,例如通过使用Table.field(String, DataType<T>)

clrs.field("bookID", BOOK.ID.getDataType())

研究您的各种选择,您可能会发现最有用的选择

一种更好的查询解决方案

您真的不需要

  1. 将您的子查询分配给局部变量
  2. 使用派生表解决问题

通常使用jOOQ,如果您在上述派生表方面遇到问题,请问自己是否真的没有一个我可以编写的更简单的查询?

这里您真正需要的是semi join。写:

// Assuming this static import
import static org.jooq.impl.DSL.*;

ctx.select(AUTHOR.LASTNAME)
   .from(AUTHOR)
   .where(AUTHOR.ID.in(
        select(BOOK_AUTHOR.AUTHORID)
       .from(BOOK_AUTHOR)
       .join(BOOK).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
       .where(BOOK.TITLE.eq(clrsTitle))
   )
   .fetch();