java - Mybatis 将多个结果集映射到对象内部集合

标签 java xml mybatis multiple-resultsets

问题简要描述

正在关注 guideline for multiple resultsetsthis answer的帮助下我现在能够提取 2 个不同的记录集,但它们只是列表,并没有映射到结果对象上。

详情

我有类(class)(简体):

public class SupplyChain{
    private String id;

    private List<SupplyChainNode> nodes;
    private List<SupplyChainEdge> edges;
}

public class SupplyChainNode {
    private String id;
    private String label;
}

public class SupplyChainEdge {
    private String id;
    private String label;
}

MyBatis接口(interface)声明如下:

public interface SupplyChainMBDao {
    List<SupplyChain> getByPartyId(@Param("partyId") String partyId);
}

MyBatis映射:

<mapper namespace="ru.rlh.egais.portal.backend.dao.mybatis.SupplyChainMBDao">
    <select id="getByPartyId" resultSets="edges,nodes" resultMap="supplyChainMapEdge, supplyChainMapNode"><![CDATA[
    -- There big query returns 2 recordset - first for Edges and second for Nodes. They have different amount of rows and logic of obtain, but share initial computation and it is desire to return them atomic.
    -- Let it be for simplicity:
    SELECT * FROM (VALUES(1, 2)) edges(id, label);

    SELECT * FROM (VALUES(2, 3), (4, 5)) nodes(id, label)
    ]]></select>

    <resultMap id="supplyChainMapEdge" type="ru.rlh.egais.portal.api.dto.bo.supplychain.SupplyChainEdge" >
        <result property="label" column="label"/>
    </resultMap>

    <resultMap id="supplyChainMapNode" type="ru.rlh.egais.portal.api.dto.bo.supplychain.SupplyChainNode" >
        <result property="label" column="label"/>
    </resultMap>
</mapper>

所以,基本上它有效,我得到了 2 个集合。但不是声明 List<SupplyChain>返回值我真的得到了List<List>其中内部列表在运行时包含 2 个元素:

  • 0 元素是List<SupplyChainEdge>
  • 和第一个:List<SupplyChainNode> .

如何将这些原始集合包装到对象中 SupplyChain ?

最佳答案

我不得不猜测“大查询返回 2 个记录集 [...]”实际上是一个存储过程,其主体由 2 个 SELECT 语句组成(正如Multiple ResultSets for Association 章节中所建议的那样)的 Mybatis doc ) 这就是您获得 2 个结果集的方式。

您确实可以尝试构建单个 SELECT 并使用集合/关联映射列。

或者您可以将您的目标集合绑定(bind)到存储过程 OUT 参数(这里适用于 Oracle):

CREATE PROCEDURE p(partyId IN VARCHAR2, rc1 OUT SYS_REFCURSOR, rc2 OUT SYS_REFCURSOR) AS
BEGIN
OPEN rc1 FOR SELECT [...];
OPEN rc2 FOR SELECT [...];
END;

这是 Mapper 接口(interface)(带有注释,您可以将其全部转换为 XML):

@Select("{ CALL p(#{partyId}),
#{supplyChain.nodes, mode=OUT, jdbcType=CURSOR, javaType=java.sql.ResultSet, resultMap=supplyChainMapNode},
#{supplyChain.edges, mode=OUT, jdbcType=CURSOR, javaType=java.sql.ResultSet, resultMap=supplyChainMapEdge} 
}")
@Options(statementType = StatementType.CALLABLE)
void getByPartyId(@Param("partyId") String partyId, @Param("supplyChain") SupplyChain supplyChain);

resultMaps 是您在 XML 中定义的那些。

因此调用映射器,当过程响应时,供应链 bean 将被填充。

无论如何,我想知道使用 SELECT 或 CURSOR 之间的行为差​​异是什么,特别是在资源管理/性能方面,考虑到 Java 最终使用结果集。 例如,我想为 fetchSize 选项设置一个自定义值(Oracle 默认值为 10,这对于大型结果集来说非常慢(太多的 java<-->DB 往返))。但到目前为止,我无法确定此语句选项是否用于绑定(bind)输出参数。

干杯。

关于java - Mybatis 将多个结果集映射到对象内部集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40071012/

相关文章:

java - 在 Java 程序中使用 JDBC 驱动程序是否可以在没有反射的情况下工作?

Java - for循环终止表达式之间的区别

c# - 使用 XmlReader 如何在开始时重新启动?

spring - 创建名为 'sqlSessionFactory' 的 bean 时出错...调用 init 方法失败;嵌套异常是 java.lang.NullPointerException

java - 如何检查字符串是否不等于对象?

java - Derby/JavaDB _真的_可以使用 Triple DES 而不是(普通的)DES 进行加密吗?

java - Spring 4、MyBatis、带注解的多数据源

java - Eclipse导入jar包,启动Tomcat还是找不到class

java - 如何使用 XML (SAXParser) 中的元素并将其显示到表中

xml - 如何用golang解码最简单的xml