You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用jOOQ将单表数据映射为嵌套结构的Catalog POJO

如何使用jOOQ将单表数据映射为嵌套结构的Catalog POJO

没问题,这个场景完全可以用jOOQ的multiset来实现,而且非常合适!咱们一步步来拆解怎么做:

你的核心需求是把单表中同一作者的所有书籍条目嵌套成List<BookEntry>,再和作者名一起封装到Catalog POJO里。jOOQ的multiset(包括multisetAgg聚合函数)刚好就是用来处理这种行转嵌套集合的场景,不管是跨表关联还是单表分组都适用。

1. 先调整POJO(确保有可映射的构造方法)

jOOQ的Records.mapping工具类需要POJO有对应参数的构造方法,我们给两个类加上构造方法(用Lombok的@AllArgsConstructor替代也可以):

import java.util.Date;
import java.util.List;

public class Catalog {
    private String author;
    private List<BookEntry> bookEntries;

    // 用于jOOQ映射的构造方法
    public Catalog(String author, List<BookEntry> bookEntries) {
        this.author = author;
        this.bookEntries = bookEntries;
    }

    // 可选:getter/setter
    public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }
    public List<BookEntry> getBookEntries() { return bookEntries; }
    public void setBookEntries(List<BookEntry> bookEntries) { this.bookEntries = bookEntries; }
}

public class BookEntry {
    private String bookName;
    private Date publicationDate;

    // 用于jOOQ映射的构造方法
    public BookEntry(String bookName, Date publicationDate) {
        this.bookName = bookName;
        this.publicationDate = publicationDate;
    }

    // 可选:getter/setter
    public String getBookName() { return bookName; }
    public void setBookName(String bookName) { this.bookName = bookName; }
    public Date getPublicationDate() { return publicationDate; }
    public void setPublicationDate(Date publicationDate) { this.publicationDate = publicationDate; }
}

2. 用multisetAgg实现单表分组嵌套(推荐)

jOOQ 3.15+提供的multisetAgg是专门的聚合函数,能直接在GROUP BY后聚合当前分组的字段为嵌套集合,代码更简洁:

// 假设你已经初始化好DSLContext实例,命名为dsl
// 给表起别名,避免字段冲突
var c = CATALOG.as("c");

List<Catalog> catalogList = dsl.select(
        c.AUTHOR,
        // 聚合当前作者的所有书籍字段,转换为List<BookEntry>
        multisetAgg(c.BOOK_NAME, c.PUBLICATION_DATE)
            .convertFrom(records -> records.map(Records.mapping(BookEntry::new)))
    )
    .from(c)
    .groupBy(c.AUTHOR) // 按作者分组
    // 把查询结果映射为Catalog对象
    .fetch(Records.mapping(Catalog::new));

3. 用关联子查询+multiset的实现方式

如果你更习惯用关联子查询的方式(和你之前跨表用multiset的逻辑更像),也可以这么写:

var c = CATALOG.as("c");

List<Catalog> catalogList = dsl.select(
        c.AUTHOR,
        // 用multiset包裹关联子查询,获取当前作者的所有书籍
        multiset(
            select(
                CATALOG.BOOK_NAME,
                CATALOG.PUBLICATION_DATE
            )
            .from(CATALOG)
            .where(CATALOG.AUTHOR.eq(c.AUTHOR)) // 关联外层的作者
        ).convertFrom(records -> records.map(Records.mapping(BookEntry::new)))
    )
    .from(c)
    .groupBy(c.AUTHOR)
    .fetch(Records.mapping(Catalog::new));

关键说明

  • 两种方式最终效果完全一致,multisetAgg是更针对聚合场景的简化写法,推荐使用。
  • jOOQ会自动处理数据库字段名到POJO属性的映射(比如BOOK_NAME对应bookName,遵循驼峰转下划线的默认规则),如果字段名规则不一致,可以用@Column注解指定,或者在查询里给字段加别名。
  • 关于日期类型:如果你的数据库用的是DATE/TIMESTAMP,jOOQ会自动映射到Java的Date;如果推荐用Java 8+的时间API(比如LocalDate),只需要把POJO里的Date改成LocalDate,jOOQ也会自动适配。

这样就能完美把单表的数据按作者分组,转换成你需要的嵌套结构POJO啦!

备注:内容来源于stack exchange,提问作者Conner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 11:17:59