Mybatis:从没有N + 1选择的select返回嵌套映射(即不使用@Many或结果映射的子查询)

时间:2014-05-22 14:53:06

标签: java mybatis ibatis

对于一个简单的查询:

select primaryKey, secondaryKey, attributeOne, attributeTwo

一个简单的域对象:

public class ExampleDto {
    Integer primaryKey;
    Integer secondaryKey;
    String attributeOne;
    String attributeTwo;
}

我想要以下内容:

Map<PrimaryKey, Map<SecondaryKey, ExamplDto>>

我目前的做法是增加一个Dto对象:

<resultMap id="ExampleCollection" type="ExampleCollectionDto" autoMapping="true">
    <id property="primaryKey" column="primaryKey" javaType="integer"/>
    <collection property="values" ofType="ExampleDto" autoMapping="true">
        <id property="primaryKey" column="primaryKey" javaType="integer"/>
        <id property="secondaryKey" column="secondaryKey" javaType="integer"/>
    </collection>
</resultMap>

public class ExampleCollectionDto {
    Integer primaryKey;
    List<ExampleDto> values;

    public Map<Integer, KeyedValue> getMap() {
        Map<Integer, ExampleDto> results;
        for(ExampleDto value : values) {
            results.put(value.secondaryKey, value);
        }
        return results;
    }
}

并通过

进行映射
public interface ExampleMapper {
    @MapKey("primaryKey")
    Map<Integer, ExampleCollectionDto> getExampleCollectionDtoMap();
}

有没有办法(通过注释或xml映射)避免必须使用基本的MyBatis功能或在结果处理流程中注入自己的收集DTO?即。

public interface ExampleMapper {
    // possibly some annotation here
    Map<Integer, Map<Integer, ExampleDto>> getExampleDtoMap();
}

到目前为止,我能够弄清楚如何执行此操作的唯一方法是遇到N + 1查询问题(我已经拥有了我需要的所有数据)。

1 个答案:

答案 0 :(得分:1)

这并不是您想要的,因为mapper界面中的方法不会直接返回值,但仍然可能是一个选项。

您可以尝试使用自定义ResultHandler发布处理结果:

ExampleMapper.xml

<resultMap id="ExampleDtoMap" type="ExampleDto" autoMapping="true">
    <id property="primaryKey" column="primaryKey" javaType="integer"/>
</resultMap>

<select id="getExampleDtoMap" resultMap="ExampleDtoMap">
    select * from example_table
</select>

ExampleMapper.java

public interface ExampleMapper {
    void getExampleDtoMap(ResultHandler handler);
}

MyService.java

class MyResultHandler implements ResultHandler {
    Map<Integer, Map<Integer, ExampleDto>> result = new HashMap<>();
    @Override
    public void handleResult(ResultContext context) { 
        ExampleDto dto = (ExampleDto)context.getResultObject(); 
        Map<Integer, ExampleDto> map = result.get(dto.primaryKey);
        if (map == null) {
            map = new HashMap<>(); 
        }                  
        map.put(dto.secondaryKey, dto);
    }
};
MyResultHandler handler = new MyResultHandler();
ExampleMapper exampleMapper = ...;
exampleMapper.getExampleDtoMap(handler);

return handler.result;