Jooq中的一对多选择

时间:2017-03-08 13:36:20

标签: java mysql one-to-many jooq

我正在尝试JOOQ并尝试使用连接语句从3个表(作者,书籍和文章)中进行选择。 ERD如下:

Author ----< Books
   |
   |
   ^
Articles

我的查询如下:

    final List<Tuple3<AuthorRecord, BooksRecord, ArticlesRecord>> tupleList =
        persistenceContext.getDslContext()
            .select()
            .from(Author.AUTHOR)
            .join(Books.BOOKS)
            .on(Author.AUTHOR.ID.eq(Books.BOOKS.AUTHOR_ID))
            .join(Articles.ARTICLES)
            .on(Author.AUTHOR.ID.eq(Articles.ARTICLES.AUTHOR_ID))
            .where(Author.AUTHOR.ID.eq(id))
            .fetch()
            .map(r -> Tuple.tuple(r.into(Author.AUTHOR).into(AuthorRecord.class),
                r.into(Books.BOOKS).into(BooksRecord.class),
                r.into(Articles.ARTICLES).into(ArticlesRecord.class)));

我还有一个protobuf对象如下:

message Author {
    int64 id = 1;
    string name = 2;
    repeated string books = 3;
    repeated string articles = 4;
}

(或任何其他pojo)将所有实体(作者详细信息+书籍列表+文章列表)保存到一个对象中。我的问题是,是否有一些方法可以使用JOOQ将所有三个表开箱即用于一个对象。

提前致谢。

1 个答案:

答案 0 :(得分:2)

您的查询效率会相当低,因为如果您以这种方式使用联接,则会在书籍和文章表之间创建cartesian product,从而导致相当多的内存和CPU消耗在删除所有无意义的组​​合之前,在数据库和Java客户端中。

&#34;正确&#34; SQL方法是使用MULTISET as described in this article here。不幸的是,jOOQ 3.9 doesn't support MULTISET yet(许多数据库也没有)。因此,您应该创建两个单独的查询:

  1. 获取所有书籍
  2. 获取所有文章
  3. 然后使用类似Java 8 Streams的内容将它们映射到单个对象中。