Search code examples
javamybatis

How to get Map from myBatis with a key of another table?


I have a request, which gives me one object of Advantage class:

<resultMap id="AdvantageResult" type="Advantage">
        <id property="id" jdbcType="BIGINT" javaType="java.lang.Long" column="id"/>
        <result property="code" column="code"/>
        <result property="name" column="name"/>
        <result property="description" column="description"/>
        <result property="asIs" column="as_is"/>
        <result property="toBe" column="to_be"/>
        <result property="availableName" column="available_name"/>
        <result property="availableNameShort" column="available_name_short"/>
        <result property="availableDescription" column="available_description"/>
        <result property="availableDescriptionShort" column="available_description_short"/>
        <result property="activeName" column="active_name"/>
        <result property="activeNameShort" column="active_name_short"/>
        <result property="activeDescription" column="active_description"/>
        <result property="activeDescriptionShort" column="active_description_short"/>
    </resultMap>

Here is my request, where I use the map:

<select id="findAdvantageByLoyaltyAndConfigDetailId" resultMap="AdvantageResult">
        select  a.id, a.code, a.name, a.description, a.as_is, a.to_be,
                a.available_name, a.available_name_short, a.available_description, a.available_description_short,
                a.active_name, a.active_name_short,  a.active_description, a.active_description_short
        from advantage a
                 left join detail_advantage da on da.advantage_id = a.id
        where da.config_detail_id = #{configDetailId}
    </select>

I want to get Map <Long, Advantage>, where the long key will be the param #{configDetailId} How should I rewrite the mapper?


Solution

  • I could think of two approaches.

    1. Convert the returned Advantage to Map in Java code.
      Defining a simple default method in the Java mapper interface should be sufficient.

      Advantage internalSelect(Long configDetailId);
      
      default Map<Long, Advantage> select(Long configDetailId) {
        return Map.of(configDetailId, internalSelect(configDetailId));
      }
      
    2. Add a private field to Advantage that holds configDetailId and use @MapKey.

      private Long configDetailId;
      

      Then include the parameter to the column list of the select and the result map.

      select ...
         , #{configDetailId} as configDetailId
      from ...
      
      <result property="configDetailId" column="configDetailId" />
      

      Then add @MapKey to your Java mapper interface.

      @MapKey("configDetailId")
      Map<Long, Advantage> findAdvantageByLoyaltyAndConfigDetailId(Long configDetailId);
      

    @MapKey is handy when there is an existing property for the 'key'.
    Otherwise, I would recommend the first approach.