用Map模拟外键关联查询是将数据库JOIN搬至内存手动实现,通过companyMap以cid为key存储公司数据、userList存用户Map,遍历用户查companyMap组装结果,支持null外键和多对一,适合中小数据量轻量场景。

用 Map 模拟外键关联查询,本质是把数据库的 JOIN 操作“搬”到内存里手动完成。它不依赖 JPA 的注解或 MyBatis 的 resultMap,适合轻量场景、快速验证逻辑,或在无法修改实体类/ORM 配置时临时使用。
准备两张表对应的数据集(用 Map 模拟)
假设你有 User 表(含字段 id、name、cid)和 Company 表(含字段 cid、companyName)。先用 Java 的 Map 存储原始数据:
- 用
Map或更清晰的> Map存公司信息,以cid为 key - 用
List存用户数据,每条记录是 Map,含"id"、"name"、"cid"等键 - 提前把 Company 数据加载进内存 Map,比如:
companyMap.put(companyCid, companyData)
手动“JOIN”:遍历 + 查找 + 组装结果
对每个用户记录,根据其 cid 去 companyMap 中查找对应公司信息,再合并成一条完整结果:
- 遍历用户列表:
for (Mapuser : userList) - 取出 cid:
Long cid = (Long) user.get("cid") - 查公司:
Map(注意判 null)company = companyMap.get(cid) - 新建结果 Map,put 所有需要字段:
result.put("userName", user.get("name"))、result.put("companyName", company != null ? company.get("companyName") : null) - 将 result 加入最终返回的 List
处理空外键与多对一关系
外键 cid 可能为 null,或多个用户指向同一公司——这正是真实业务常见情况:
- 查 companyMap 时直接用
get(cid),天然支持 null 外键:查不到就返回 null,组装时填默认值或保留 null 即可 - 无需额外去重或分组,同一个 cid 被多次查 companyMap,性能无损(HashMap O(1) 查找)
- 若需一对多(如查某公司下所有用户),可反向构建
Map,按 cid 分组用户列表>
对比 SQL JOIN 的关键差异
这种模拟方式不是替代,而是补充。它更灵活,但也需你主动管理:
- 数据库 JOIN 是基于索引的高效磁盘操作;Map 方式是全内存、单线程遍历,适合中小数据量(几千到几万条)
- 没有自动类型转换或 NULL 安全,字段取值要显式强转,比如
(String) map.get("name") - 不支持复杂条件(如 WHERE u.status = 'active' AND c.type IN ('A','B')),这些得写在遍历逻辑里
- 好处是逻辑完全可控:可插日志、加缓存判断、动态拼字段、甚至混入 HTTP 调用补数据










