首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis @MapKey 注解詳解:實現復雜 Map 結構結果映射

     編輯:Java 綜合教學

MyBatis @MapKey 注解詳解:實現復雜 Map 結構結果映射

當查詢結果需要映射為 Map<K, V> 且 Key 非主鍵、或需嵌套 Map<String, Map<String, Object>> 等復雜結構時,@MapKey 注解提供了聲明式的解決方案,避免手動在 Service 層轉換。

注解定義

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MapKey {
    String value(); // 指定結果對象中作為 Map Key 的屬性名
}

核心用法

場景一:List<User> → Map<String, User> (以 userName 為 Key)

@Select("SELECT * FROM users")
@MapKey("userName")
Map<String, User> selectUsersMap();

結果:{"zhangsan": User{id=1, userName="zhangsan", ...}, "lisi": User{id=2, ...}}

場景二:多表關聯查詢 → Map<String, Map<String, Object>>

@Select("SELECT u.id, u.name, o.id AS orderId, o.amount FROM users u LEFT JOIN orders o ON u.id = o.user_id")
@MapKey("name")
Map<String, Map<String, Object>> selectUserOrdersMap();

結果:{"zhangsan": {id=1, name="zhangsan", orderId=101, amount=99.9}, ...}

注意:若一對多關聯導致同一 Key 多條記錄,後者會覆蓋前者。此時應改用 @ResultMap 配合 collection 或手動分組。

原理剖析

MyBatis 在 DefaultResultSetHandler 中處理結果集時,若檢測到方法返回類型為 Map 且標註了 @MapKey,會:

  1. 遍歷結果集每一行,映射為對象/Map(V)。
  2. 從 V 中取出 @MapKey("propName") 指定屬性值作為 K。
  3. 存入 LinkedHashMap<K, V> 保持插入順序。

進階技巧與注意事項

  • Key 重複處理:默認後覆蓋前。需去重可在 SQL 加 DISTINCT 或用 GROUP BY key_col。
  • 嵌套 Map:返回類型聲明為 Map<K, Map<K2, V>> 時,外層 Key 由 @MapKey 指定,內層 Map 由列名自動映射。
  • 配合 @ResultMap:復雜映射(嵌套對象、類型轉換器)優先用 XML <resultMap>,接口方法僅標註 @MapKey。
  • 泛型擦除:接口方法簽名需保留完整泛型信息(Map<String, User>),MyBatis 通過 TypeParameterResolver 解析實際類型。
  • 性能提示:大結果集轉 Map 會佔用額外內存,必要時分頁或流式處理。

對比:XML 配置方式

<select id="selectUsersMap" resultType="com.entity.User">
    SELECT * FROM users
</select>
<!-- 在 Mapper 接口方法上加 @MapKey("userName") 即可 -->

XML 本身無 mapKey 屬性,需配合注解或在代碼中手動轉換。

總結

@MapKey 是 MyBatis 為 Map 結構結果映射提供的輕量級注解,適用於「單列為 Key、整行/對象為 Value」的簡單場景。復雜嵌套、一對多聚合、去重邏輯建議使用 ResultHandler、ResultMap 或 Service 層二次加工。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved