jOOQ - присоединиться к вложенному подзапросу - PullRequest
0 голосов
/ 19 марта 2019

Допустим, я хочу выяснить, кто написал CLRS в книге дБ (таблицы BOOK, 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))
        ;

Немного неэффективно длясопоставьте всю таблицу, просто чтобы выбрать одну книгу.Теперь я хочу выбрать эту книгу перед матчем.

Документ JOOQ по этому вопросу привел меня к мысли, что это может выглядеть примерно так:

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 Ответ

1 голос
/ 20 марта 2019

Проблема, с которой вы столкнулись

Вы разыменовываете столбец из производной таблицы, используя 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();
...