有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Mybatis:从select返回嵌套映射,不使用N+1 selects(即不使用@Many或结果映射子查询)

对于一个简单的查询:

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映射)可以避免收集DTO,或者使用基本的MyBatis功能,或者通过在结果处理流中注入我自己?即

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

到目前为止,我唯一能够弄清楚如何做到这一点的方法是N+1查询问题(我已经有了所需的所有数据)


共 (1) 个答案

  1. # 1 楼答案

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

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

    示例映射器。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>
    

    示例映射器。爪哇

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

    我的服务。爪哇

    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;