Understanding and Using @MapKey Annotation in MyBatis
This article explains how to use MyBatis's @MapKey annotation to map query results into a Java Map, compares common data‑retrieval approaches, provides a concrete example with mapper code, and delves into the internal parsing and result‑handling mechanisms that enable key‑value mapping.
When developing with MyBatis, you often need to extract a specific record from a large result set. Common solutions include embedding where clauses in SQL, iterating over all results in Java, or using the @MapKey annotation to store results directly in a Map keyed by a chosen field.
The first two approaches are straightforward but can be inefficient for large data sets. The article focuses on the third approach, which leverages MyBatis's @MapKey to automatically build a Map where each entry's key is derived from a property of the result object.
Basic Usage Example
Assume a User class with fields id, age, and name. To retrieve all users and map them by id, define a mapper interface as follows:
@Mapper
public interface EmployeeMapper {
@Select("SELECT id, name, age FROM test_user")
@MapKey("id")
Map<Integer, User> getAllUser();
}Calling getAllUser() returns a Map where each key is a user’s id and each value is the corresponding User object.
Internal Working Principle
MyBatis parses the @MapKey annotation during the configuration phase. The parsing logic resides in the internal MethodSignature class, which extracts the annotation value and stores it in a private mapKey field:
public static class MethodSignature {
// ... other fields and methods omitted
// Stores the key defined in @MapKey
private final String mapKey;
public MethodSignature() {
// ... initialization omitted
this.mapKey = getMapKey(method);
// ... other initialization omitted
}
}When a mapper method annotated with @MapKey is invoked, MyBatis creates a MapperProxy that delegates the call to a MapperMethod. The MapperMethod determines the SQL to execute, the method parameters, and the expected return type. After the SQL query runs, the result set is processed by the default result handler DefaultMapResultHandler, whose core logic is:
public void handleResult(ResultContext<? extends V> context) {
final V value = context.getResultObject();
final MetaObject mo = MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
// TODO is that assignment always true?
final K key = (K) mo.getValue(mapKey);
mappedResults.put(key, value);
}This method extracts the field specified by mapKey from each result object, uses it as the map key, and stores the object as the corresponding value.
Summary of the Process
Annotation Parsing: MyBatis scans the mapper interface, detects @MapKey, and records the designated key field.
SQL Execution: The annotated method triggers the associated SQL query.
Result Set Mapping: MyBatis iterates over each row, creates an instance of the result type, and populates it with column values.
Key‑Value Insertion: Using the previously parsed key field, MyBatis inserts each object into the resulting Map as a value keyed by that field.
Overall, the @MapKey annotation provides a concise way to transform query results into a keyed map, simplifying data retrieval patterns that require fast lookup by a specific attribute.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
