MyBatis @MapKey 注解详解
一句话总结MapKey告诉 MyBatis把查询结果的某一列作为 Map 的 key整行数据作为 value。 为什么需要 MapKey场景查询多条记录想通过某个字段快速查找假设你有以下数据idnameemail1张三zhangexample.com2李四liexample.com3王五wangexample.com你想通过id快速找到对应的用户。❌ 没有 MapKey 的情况Mapper 接口ListMapString,ObjectqueryUsers();返回结果[{id1,name张三,emailzhangexample.com},{id2,name李四,emailliexample.com},{id3,name王五,emailwangexample.com}]使用方式麻烦ListMapString,Objectlistmapper.queryUsers();// 想找到 id2 的用户需要遍历MapString,Objecttargetnull;for(MapString,Objectrow:list){if(Integer.valueOf(2).equals(row.get(id))){targetrow;break;}}问题每次查找都要遍历整个列表性能差✅ 有 MapKey 的情况Mapper 接口MapKey(id)// ← 指定用 id 作为 keyMapString,MapString,ObjectqueryUsers();返回结果{1:{id1,name张三,emailzhangexample.com},2:{id2,name李四,emailliexample.com},3:{id3,name王五,emailwangexample.com}}使用方式简单MapString,MapString,Objectmapmapper.queryUsers();// 想找到 id2 的用户直接 getMapString,Objecttargetmap.get(2);优势O(1) 时间复杂度瞬间找到 MapKey 的工作原理形象比喻想象你有一堆名片没有 MapKey名片堆在一起想找张三的名片 → 必须一张张翻直到找到为止 有 MapKey名片按名字排好序放在抽屉里想找张三 → 直接打开张字抽屉瞬间拿到 技术实现MapKey(id)MapString,MapString,ObjectqueryUsers();MyBatis 会执行 SQL得到多行结果遍历每一行取出该行的id列的值如 “1”、“2”、“3”把这一整行数据作为 value组成Map1, 该行数据、Map2, 该行数据… 对比总结特性没有 MapKey有 MapKey返回类型ListMapK,VMapString, MapK,V查找方式遍历列表直接 get(key)时间复杂度O(n)O(1)代码可读性差好适用场景只需要遍历需要通过某列快速查找 常见误区误区 1MapKey 只能用于 Map 返回值❌错误理解MapKey只能配合Map返回类型使用✅正确理解MapKey可以用于任何返回多条记录的查询包括MapString, Object- 单条记录MapString, MapString, Object- 多条记录MapString, YourDO- 多条记录映射到对象误区 2MapKey 的值可以是任意字段❌错误用法MapKey(non_existent_column)// 这个字段在 SQL 中不存在✅正确用法MapKey(id)// 必须是 SELECT 中的列名误区 3MapKey 会自动去重❌如果有重复的 keySELECTid,...FROMtable-- 结果-- 1-- 1 ← 重复后面的会覆盖前面的✅解决方案SELECTDISTINCTid,...FROMtable 最佳实践1. 明确是否需要快速查找// 只需要遍历 → 不需要 MapKeyListUserlistmapper.selectAll();for(Useru:list){...}// 需要通过 ID 查找 → 需要 MapKeyMapKey(id)MapString,Usermapmapper.selectAll();Userumap.get(123);2. 选择合适的 key 字段// ✅ 好的选择唯一、非空、简短MapKey(id)MapKey(user_code)// ❌ 不好的选择可能重复、可能为空、太长MapKey(description)MapKey(email)// 邮箱可能很长3. 配合 Java 8 Stream 使用// 如果 Mapper 返回 List可以用 Stream 转 MapListUserlistmapper.selectAll();MapString,Usermaplist.stream().collect(Collectors.toMap(User::getId,u-u)); 总结MapKey的本质把数据库查询结果从列表变成字典让你可以通过某个字段快速查找记录。什么时候用✅ 需要通过某列快速查找✅ 避免多次遍历列表✅ 提高代码可读性什么时候不用❌ 只需要遍历所有数据❌ 只有一条记录❌ key 字段不唯一