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

表无直接关联时,如何正确使用MyBatis的collection属性?

问题描述

测试数据

t1
pk | a     | b   | c     | other1
1  | text1 | 123 | text3 | otherValues1
2  | text2 | 456 | text4 | otherValues2

t2
pk | fk | d     | e  | other2
1  | 1  | text5 | 10 | otherValues3
2  | 1  | text6 | 20 | otherValues4 
3  | 1  | text7 | 30 | otherValues5
4  | 2  | text8 | 40 | otherValues6

实体类

@Data
public class Pojo1 {
  private String p11;
  private Integer p12;
  private String p13;
  private List<Pojo2> list;
}

@Data
public class Pojo2 {
  private String p21;
  private Integer p22;
}

期望输出

{
  "p11": "text1",
  "p12": 123,
  "p13": "text3",
  "list": [ 
            {"p21":"text5","p22":10},
            {"p21":"text6","p22":20},
            {"p21":"text7","p22":30}
          ]
}

限制条件

  • 响应属性与数据库列名不一致,需要映射
  • 必须分开执行两个查询,无法关联查询:
select a, b, c, other1 from table t1 where t1.pk = ${key1}

select d, e, other2 from table t2 where t2.fk = ${key1}

当前配置及问题

Mapper配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="something.MyMapper">

    <resultMap id="map1" type="Pojo1">
        <result column="a" property="p11"/>
        <result column="b" property="p12"/>
        <result column="c" property="p13"/>
        <collection property="list" column="dontKnowWhatToPutHere" ofType="Pojo2" select="select2"/>
    </resultMap>

    <select id="select1" resultMap="map1">
        select a, b, c, other1 from table t1 where t1.pk = ${key1}
    </select>

    <resultMap id="map2" type="Pojo2">
        <result column="d" property="p21"/>
        <result column="e" property="p22"/>
    </resultMap>

    <select id="select2" resultMap="map2">
        select d, e, other2 from table t2 where t2.fk = ${key1}
    </select>

</mapper>

当前返回结果:

{
  "p11": "text1",
  "p12": 123,
  "p13": "text3",
  "list": null
}

已知添加虚拟硬编码列的方案可行,询问是否有其他方案。


可行解决方案

除了添加虚拟硬编码列的方式,还有以下几种可行方案:

1. 主查询返回主键列,通过column传递参数

修改主查询返回t1.pk列(即使实体类无对应属性也不影响),将其作为参数传递给嵌套查询:

  • 修改select1的SQL:
select pk, a, b, c, other1 from table t1 where t1.pk = ${key1}
  • 修改map1中的collection配置:
<collection property="list" column="pk" ofType="Pojo2" select="select2"/>
  • 调整select2的SQL,使用参数占位符(推荐用#替代$防止SQL注入):
select d, e, other2 from table t2 where t2.fk = #{pk}

MyBatis会自动将主查询返回的pk值传入select2,完成关联查询并填充list。

2. Service层手动组装数据

不依赖MyBatis嵌套查询,在Service层分别调用两个Mapper方法获取数据后手动组装:

@Service
public class MyService {
    @Autowired
    private MyMapper myMapper;

    public Pojo1 getPojo1(String key1) {
        Pojo1 pojo1 = myMapper.select1(key1);
        List<Pojo2> pojo2List = myMapper.select2(key1);
        pojo1.setList(pojo2List);
        return pojo1;
    }
}

这种方式逻辑直观,完全由开发者控制数据组装,适合查询逻辑复杂的场景。

3. column传递固定参数(参数固定场景适用)

如果${key1}是固定值,可直接在column中硬编码参数:

<collection property="list" column="fk=${key1}" ofType="Pojo2" select="select2"/>

同时修改select2的SQL:

select d, e, other2 from table t2 where t2.fk = #{fk}

此方式灵活性差,仅适用于参数固定的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:35:01