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

如何在R2DBC中将查询结果映射到含List类型字段的实体?

解决R2DBC中关联List字段映射重复对象的问题

你的问题根源在于JOIN查询返回的每一行都会被映射成独立的Employee对象,每个对象仅包含当前行对应的单个Account。要实现合并相同Employee的Account列表,需要在Flux流中对查询结果做分组合并处理。

步骤1:补全SQL查询字段

你的SQL语句遗漏了a.employeeId字段,必须补充才能正确映射Account的employeeId属性:

SELECT e.id, e.name, e.surname, a.employeeId, a.accountNumber 
FROM employee e 
JOIN account a on e.id = a.employeeId 
WHERE e.id = :id

步骤2:调整映射逻辑为可变列表

原映射用List.of()创建的是不可变列表,后续无法添加元素,需要改为可变的ArrayList:

public static final BiFunction<Row, RowMetadata, Employee> EMPLOYEE_MAPPER =
        (row, rowMetadata) -> Employee.builder()
                .id(row.get("id", Long.class)) // 匹配实体类的Long类型id
                .name(row.get("name", String.class))
                .surname(row.get("surname", String.class))
                .accounts(new ArrayList<>(List.of(new Account(
                        row.get("employeeId", String.class), 
                        row.get("accountNumber", String.class)
                ))))
                .build();

步骤3:分组合并Employee对象

在仓库方法中,通过groupBy按Employee的id分组,再用reduce合并同组内的Account列表:

public Flux<Employee> findCardByPan(Long id) {
    return databaseClient.sql("SELECT e.id, e.name, e.surname, a.employeeId, a.accountNumber FROM employee e JOIN account a on e.id = a.employeeId WHERE e.id = :id")
            .bind("id", id)
            .map(EMPLOYEE_MAPPER)
            .groupBy(Employee::getId) // 按Employee ID分组
            .flatMap(group -> group.reduce((emp1, emp2) -> {
                // 合并两个Employee的Account列表
                emp1.getAccounts().addAll(emp2.getAccounts());
                return emp1;
            }));
}

补充优化建议

  • 可以在Employee实体类中直接初始化accounts为可变列表,简化映射逻辑:
    private List<Account> accounts = new ArrayList<>();
    
  • 若需处理LEFT JOIN(Employee可能无关联Account)的场景,可在映射时判断accountNumber是否为null,避免添加空Account对象。

内容的提问来源于stack exchange,提问作者ilham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:50:22