mybatis如何聚合字段成为新字段

zxbandzby
1
2025-06-17

比如mybatis要查询 一个主表a 一个子表b 我想把子表的fk_pro_id聚合到 主表里面去逗号分割,那么我需要怎么做呢?

方案一:SQL层面聚合(推荐)​​

​1. SQL语句设计​

使用数据库的聚合函数(如MySQL的GROUP_CONCAT)直接在SQL中完成字段拼接:

sql

复制

SELECT 
    a.*, 
    GROUP_CONCAT(b.fk_pro_id) AS pro_ids
FROM 
    main_table a
LEFT JOIN 
    sub_table b ON a.id = b.fk_main_id
GROUP BY 
    a.id;

​2. MyBatis映射配置​

在Mapper XML中定义resultMap,将聚合结果映射到Java对象的属性:

xml

复制

<resultMap id="MainResultMap" type="MainEntity">
    <id property="id" column="id"/>
    <!-- 其他主表字段映射 -->
    <result property="proIds" column="pro_ids"/> <!-- 聚合字段 -->
</resultMap>

<select id="selectMainWithAggregatedSub" resultMap="MainResultMap">
    SELECT 
        a.*, 
        GROUP_CONCAT(b.fk_pro_id) AS pro_ids
    FROM 
        main_table a
    LEFT JOIN 
        sub_table b ON a.id = b.fk_main_id
    GROUP BY 
        a.id;
</select>

​3. Java实体类定义​

java

复制

public class MainEntity {
    private Long id;
    private String proIds; // 逗号分隔的子表ID集合
    // 其他字段及getter/setter
}

​方案二:MyBatis嵌套查询 + Java处理​

​1. 主查询获取主表数据​

xml

复制

<select id="selectMainList" resultType="MainEntity">
    SELECT * FROM main_table;
</select>

​2. 子查询获取关联子表数据​

xml

复制

<select id="selectSubByMainId" resultType="String">
    SELECT fk_pro_id FROM sub_table WHERE fk_main_id = #{mainId}
</select>

​3. Java代码拼接​

在Service层通过循环调用子查询,将结果拼接为逗号分隔字符串:

java

复制

List<MainEntity> mainList = mainMapper.selectMainList();
mainList.forEach(main -> {
    List<String> subIds = subMapper.selectSubByMainId(main.getId());
    main.setProIds(String.join(",", subIds));
});

​方案对比与建议​

维度

方案一(SQL聚合)​

方案二(嵌套查询)​

性能

单次查询,数据库原生聚合效率高

多次查询,网络开销大

代码复杂度

需熟悉SQL聚合函数

逻辑分离,但需处理循环拼接

灵活性

依赖数据库函数(如MySQL的GROUP_CONCAT)

通用性强,可自定义拼接逻辑

分页支持

直接支持分页

需额外处理分页与子查询关联

推荐场景​:

  • 方案一​:数据量较大、对性能敏感、数据库支持聚合函数。

  • 方案二​:需要动态拼接逻辑、无法使用数据库聚合函数。


​扩展优化​

  1. 去重处理
    在SQL聚合时添加DISTINCT关键字避免重复:

    sql

    复制

    GROUP_CONCAT(DISTINCT b.fk_pro_id)
  2. 排序控制
    指定子表数据的聚合顺序:

    sql

    复制

    GROUP_CONCAT(b.fk_pro_id ORDER BY b.create_time DESC)
  3. 分页兼容性
    若需分页,建议在SQL聚合后通过LIMITOFFSET实现,避免嵌套查询导致分页失效。

  4. 数据库兼容性
    若使用非MySQL数据库(如Oracle),需替换为等效函数(如LISTAGG)。

动物装饰