簡體   English   中英

Mybatis將多個結果集映射到對象內部集合中

[英]Mybatis map multiple resultsets into object inner collections

簡要問題描述

遵循多個結果集的指導原則並在此答案的幫助下,我現在能夠提取2個不同的記錄集,但它們只是列表而不是映射到結果對象。

詳情

我有課程(簡化):

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接口聲明如下:

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>
  • 和1st: List<SupplyChainNode>

如何將這個原始集合包裝到對象SupplyChain

另一種方法:使用自定義ResultHandler。 我已調試,直到DefaultResultSetHandler.handleResultSets,並發現提供的自定義結果處理程序用於每個“子”結果集而不是全局查詢。 然后,結果列表必須直接在期望的位置構建:在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);

我希望這符合你的期望。 無論如何,我認為這是問題的答案:將集合包裝到對象SupplyChain中。

干杯

我必須猜測“大查詢返回2記錄集[...]”實際上是一個存儲過程,其主體包含2個SELECT語句(正如Mybatis doc中 關聯章節的多個ResultSet中所建議的那樣)這就是你如何獲得2結果集。

您可能確實嘗試構建單個SELECT並使用集合/關聯映射列。

或者您可以將目標集合綁定到存儲過程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接口(帶注釋,你可以將它全部轉換為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中定義的那些。

因此,當程序響應時,調用映射器並填充SupplyChain bean。

無論如何,我想知道使用SELECT或CURSOR之間的行為差​​異是什么,特別是關於資源管理/性能,考慮到Java最終可以使用resultSets。 例如,我想為fetchSize選項設置一個自定義值(Oracle默認值為10,對於大型結果集來說非常慢(過多的java < - > DB往返))。 但到目前為止,我無法弄清楚這個語句選項是否用於綁定out-params。

干杯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM