【问题标题】:How can I populate parameters map with result set in MyBatis如何使用 MyBatis 中的结果集填充参数映射
【发布时间】:2016-07-23 14:21:27
【问题描述】:

我正在阅读一本书“MyBatis in Practice”,但不知道为什么第 67-68 页的代码不起作用。这是问题所在。这是关于调用存储过程并且它可以工作,但真正的问题是我无法弄清楚如何使用结果集填充输入映射。所以这是主类的代码:

public void callReadAllPets() throws Exception {
    HashMap<String, List<PetDVO>> inputMap = new HashMap<String, List<PetDVO>>();
    List<PetDVO> petList = new ArrayList<PetDVO>();
    inputMap.put("petData", petList);
    //
    getSqlSession().selectList("callReadAllPets", inputMap);
    List<PetDVO> outputData = inputMap.get("petData");
    printResultList(outputData, "read_all_pets");
}

private void printResultList(List<PetDVO> list) {
    for (PetDVO item : list) {
        System.out.println("     owner: " + item.getOwner());
        System.out.println("   species: " + item.getSpecies());
        System.out.println("       sex: " + item.getSex());
    }
}

PetDVO 只是一个 Java POJO。 这是mapper.xml中的代码

<select id="callReadAllPets" resultType="PetDVO" statementType="CALLABLE">
 CALL read_all_pets('SELECT name, owner, species, sex, birth, death FROM pet')

运行之前的代码后,outputData 列表为空,即未填充结果。这是书中建议的方式,但它对我不起作用?我该如何解决这个问题? p.s. 我正在使用 MyBatis 3.2.3

【问题讨论】:

  • 您的调用语句似乎没有任何名为“petData”的输出参数?
  • 嗯...@Florian Schaetz,这听起来很合理,但我现在无法检查它,因为我没有书。这看起来像书中的 lapsus calami,因为似乎正确的答案可能是 resultMap="petData" 而不是 resultType="PetDVO",但我不记得在映射器文件的任何地方看到 petData 映射?我稍后会检查它。谢谢。
  • 我还是很困惑,因为您正在执行 resultType,这意味着您希望 callReadAllPets 返回一个值,但您没有从getSqlSession().selectList( 获得返回值。相反,您似乎期望它在参数对象中,实际上没有任何 OUT 参数...
  • 如果您实际上并不期望从 selectList 中返回某些内容,那么您不需要在映射器中使用 returnType...那么您的语句中的 OUT 参数就足够了。所以我假设你在这里只需要List&lt;PetDVO&gt; outputData = getSqlSession().selectList("callReadAllPets", inputMap);
  • 是的,我知道我可以通过这种方式解决问题,而且我之前也做过很多次,但我想知道书中给出的解决方案。为什么这不起作用,我怎样才能使它起作用?

标签: java mybatis


【解决方案1】:

好的,如果你想用存储过程的 OUT 参数填充输入参数,你可以这样做......

<mapper namespace="com.example.SomeMapper">    
    <select id="doSomething" statementType="CALLABLE" parameterType="com.example.SomeRequest">
    { call someProcedure (
        #{someParameter,javaType=Long,jdbcType=NUMERIC,mode=IN},
        #{out,javaType=Long,jdbcType=NUMERIC,mode=OUT})
    }
    </select >
</mapper>

你的com.example.SomeRequest 类看起来像这样......

class SomeRequest {

    private Long someParameter;
    private Long out;

    // add Getters & Setters

}

这应该允许您从SomeRequest.out 变量中检索(长)结果。要映射更复杂的结果,您需要将它们定义为 ResultSet 并提供 ResultMap,例如...

#{out,javaType=java.sql.ResultSet,jdbcType=CURSOR,resultMap=someResultMap,mode=OUT}

至少,这就是我们使用 Oracle 数据库和包函数的方式。希望它也能以同样的方式与 MySql 存储过程一起使用......

【讨论】:

    【解决方案2】:

    感谢您的回答,但我正在使用 H2。 H2中没有存储过程,只有存储函数,实际上是普通的java方法。在这种情况下,存储函数返回 ResultSet 并使用查询 'SELECT name, owner, species, sex, birth, death FROM pet' 直接调用此函数会产生正确的结果。因此,我相信 MyBatis 知道生成的 ResultSet 但无法将其放回 inputMap 中。为了澄清这个问题,我将做两件事。首先,我要检查resultMap="petData" will work instead of resultType="PetDVO",因为petData 已经是inputMap 的一个参数。如果这不起作用,我会向自己保证 MyBatis 正在使用上述方法List&lt;PetDVO&gt; outputData = getSqlSession().selectList("callReadAllPets", inputMap) 接收结果集。不幸的是,我可以在几个小时后尝试一下。再次感谢@Florian Schaetz。

    【讨论】:

    • 不,resultMap="petData" 不起作用。我会坚持使用List&lt;PetDVO&gt; outputData = getSqlSession().selectList("callReadAllPets", inputMap),因为它完美无缺。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多