Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Mybatis将多个结果集映射到对象内部集合 简要问题描述_Java_Xml_Mybatis_Multiple Resultsets - Fatal编程技术网

Java Mybatis将多个结果集映射到对象内部集合 简要问题描述

Java Mybatis将多个结果集映射到对象内部集合 简要问题描述,java,xml,mybatis,multiple-resultsets,Java,Xml,Mybatis,Multiple Resultsets,在下面和的帮助下,我现在能够提取2个不同的记录集,但它们只是列表,并没有映射到结果对象上 详细地 我有课程(简化): 和MyBatis映射: <mapper namespace="ru.rlh.egais.portal.backend.dao.mybatis.SupplyChainMBDao"> <select id="getByPartyId" resultSets="edges,nodes" resultMap="supplyChainMapEdge, supply

在下面和的帮助下,我现在能够提取2个不同的记录集,但它们只是列表,并没有映射到结果对象上

详细地 我有课程(简化):

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>

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

  • 0元素是
    列表
  • 第一名:
    列表
如何将这些原始集合包装到对象
供应链中

我不得不猜测,“大查询返回2个记录集[…]”实际上是一个存储过程,其主体由2个SELECT语句组成(正如本章的多个关联结果集中所建议的那样) 这就是获得2个结果集的方法

您确实可以尝试构建一个单独的选择,并使用集合/关联映射列

或者,您可以将目标集合绑定到存储过程输出参数(这是针对Oracle的):

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

结果映射是您在XML中定义的映射

因此,调用映射器,当过程响应时,SupplyChainbean将被填充

无论如何,我想知道使用select和cursor之间的行为差异是什么,特别是在资源管理/性能方面,考虑到Java最终会使用resultset。 例如,我想为fetchSize选项设置一个自定义值(Oracle默认值为10,这对于大型结果集来说非常慢(javaDB往返太多))。但到目前为止,我还不知道这个语句选项是否用于绑定参数


干杯。

另一种方法:使用自定义ResultHandler。 我一直调试到DefaultResultSetThandler.HandlerResultSets,发现提供的自定义结果处理程序用于每个“子”结果集,而不是全局查询。 然后,结果列表必须直接构建在预期的位置:在supplyChain对象中

/* the Custom Result Handler  */
public class CustomResultHandler implements ResultHandler {
    private SupplyChain supplyChain;

    public CustomResultHandler(SupplyChain supplyChain) {
        this.supplyChain = supplyChain;
    }
    @Override
    public void handleResult(ResultContext ctx) {
        Object o = ctx.getResultObject();
        /* access to SupplyChain members is simplified here */
        if (o instanceof SupplyChainEdge) {
            SupplyChainEdge sc = (SupplyChainEdge) o;   
            if (ctx.getResultCount() == 1) { /* lazy list instantiation */
                this.supplyChain.supplyChainEdge = new ArrayList<SupplyChainEdge>();
            }
            this.supplyChain.supplyChainEdge.add(sc);
        } else if (o instanceof SupplyChainNode) {
            SupplyChainNode sc = (SupplyChainNode) o;
            if (ctx.getResultCount() == 1) { /* lazy list instantiation */
                this.supplyChain.supplyChainNode = new ArrayList<SupplyChainNode>();
            }
            this.supplyChain.supplyChainNode.add(sc);
        }   
    }
}

/* in mapper interface  */
void getByPartyId(@Param("partyId") String partyId, ResultHandler handler);

/* how to call it */
SupplyChain supplyChain = new SupplyChain();
ResultHandler handler = new CustomResultHandler();
mapper.getByPartyId(id, handler);
/*自定义结果处理程序*/
公共类CustomResultHandler实现ResultHandler{
私人供应链供应链;
公共CustomResultHandler(供应链供应链){
this.supplyChain=supplyChain;
}
@凌驾
公共无效句柄结果(结果上下文ctx){
对象o=ctx.getResultObject();
/*此处简化了对供应链成员的访问*/
if(o SupplyChainEdge的实例){
SupplyChainEdge sc=(SupplyChainEdge)o;
如果(ctx.getResultCount()==1){/*惰性列表实例化*/
this.supplyChain.supplyChainEdge=new ArrayList();
}
this.supplyChain.supplyChainEdge.add(sc);
}else if(o SupplyChainNode的实例){
供应链节点sc=(供应链节点)o;
如果(ctx.getResultCount()==1){/*惰性列表实例化*/
this.supplyChain.supplyChainNode=new ArrayList();
}
this.supplyChain.supplyChainNode.add(sc);
}   
}
}
/*在映射器接口中*/
void getByPartyId(@Param(“partyId”)字符串partyId,ResultHandler处理程序);
/*怎么称呼它*/
SupplyChain SupplyChain=新的SupplyChain();
ResultHandler=新的CustomResultHandler();
getByPartyId(id,处理程序);
我希望这符合你的期望。 无论如何,我认为这就是问题的答案:将集合包装到对象供应链中


干杯

请查看
高级结果映射
部分:我没有找到关于几个结果的描述。您只需要查询属于不同
结果映射
的列。这是我的代码片段:选择,从main m LEFT JOIN(选择f.id、f.main\u id、f.feature\u id、d.label feature\u name,从feature f LEFT JOIN sys\u dict d ON d.id=f.feature\u id,其中d.type='feature')ft ON ft.main_id=m.id我有一个类
main
,有一个
列表
。所以,基本上你坚持我应该将它包装在一个结果集中?我不使用存储过程,只想从两个单独的结果映射。那么你能在中给出SQL查询的一个简化版本吗?我已经添加了有问题的示例查询(Postgres)我很困惑,因为Oracle DB拒绝了这个multiple-select语句。我的博士后成绩和你一样。添加了一个新的答案(新方法)。它更接近解决方案。但是
CustomResultHandler
是实现细节。它是否可以自动在XML或接口中绑定?它不能是API的公共部分,也不能在每个DAO调用中手动使用。在单个调用中获取多个结果集不是最常见的用例。而Mybatis lib(还)不是“自动”的。然后需要扩展/覆盖。要从API中隐藏结果处理程序,您必须包装调用
session.select(“getByPartyId”,id,Handler)
mapper.getByPartyId(id,处理程序)
<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>
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;
@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);
/* the Custom Result Handler  */
public class CustomResultHandler implements ResultHandler {
    private SupplyChain supplyChain;

    public CustomResultHandler(SupplyChain supplyChain) {
        this.supplyChain = supplyChain;
    }
    @Override
    public void handleResult(ResultContext ctx) {
        Object o = ctx.getResultObject();
        /* access to SupplyChain members is simplified here */
        if (o instanceof SupplyChainEdge) {
            SupplyChainEdge sc = (SupplyChainEdge) o;   
            if (ctx.getResultCount() == 1) { /* lazy list instantiation */
                this.supplyChain.supplyChainEdge = new ArrayList<SupplyChainEdge>();
            }
            this.supplyChain.supplyChainEdge.add(sc);
        } else if (o instanceof SupplyChainNode) {
            SupplyChainNode sc = (SupplyChainNode) o;
            if (ctx.getResultCount() == 1) { /* lazy list instantiation */
                this.supplyChain.supplyChainNode = new ArrayList<SupplyChainNode>();
            }
            this.supplyChain.supplyChainNode.add(sc);
        }   
    }
}

/* in mapper interface  */
void getByPartyId(@Param("partyId") String partyId, ResultHandler handler);

/* how to call it */
SupplyChain supplyChain = new SupplyChain();
ResultHandler handler = new CustomResultHandler();
mapper.getByPartyId(id, handler);