【问题标题】:MyBatis set fetch size on ResultSet as out parameter of procedureMyBatis 将 ResultSet 上的获取大小设置为过程的输出参数
【发布时间】:2015-06-23 09:28:07
【问题描述】:

我有需要使用 MyBatis 调用的存储过程。无论如何,我设法调用了这个存储过程。过程有多个输出参数。 out 参数之一是 oracle cursor。我需要遍历 Oracle Cursor,但是当我在没有使用 fetchSize 属性对 jdbc 驱动程序进行任何微调的情况下执行此操作时,它会逐行进行,并且此解决方案非常慢。 我可以设置过程调用 fethcSize 属性:

<select id="getEvents" statementType="CALLABLE" parameterMap="eventInputMap" fetchSize="1000">
    {call myProc(?, ?, ?, ?, ?)}
</select>

但这根本没有帮助。我认为这不起作用,因为有多个输出参数 - 所以程序不知道应该在哪里应用这个提取大小 - 哪个输出参数。有没有办法在 ResultSet(Oracle 游标)上设置提取大小?就像我使用 java.sql 包中的 CallableStatemen 时一样,我可以设置 ResultSet 获取大小。

这里是映射文件和来自程序的过程调用:

  <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
          "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<mapper namespace="mypackage.EventDao">

    <resultMap id="eventResult" type="Event">
        <result property="id" column="event_id" />
        <result property="name" column="event_name" />
    </resultMap>

    <parameterMap id="eventInputMap" type="map" >
        <parameter property="pnNetworkId" jdbcType="NUMERIC" javaType="java.lang.Integer" mode="IN"/>
        <parameter property="pvUserIdentityId" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
        <parameter property="result" resultMap="eventResult" jdbcType="CURSOR" javaType="java.sql.ResultSet" mode="OUT" />
        <parameter property="success" jdbcType="INTEGER" javaType="java.lang.Integer" mode="OUT"/>
        <parameter property="message" jdbcType="VARCHAR" javaType="java.lang.String" mode="OUT"/>
    </parameterMap>



    <select id="getEvents" statementType="CALLABLE" parameterMap="eventInputMap" fetchSize="1000">
        {call myProc(?, ?, ?, ?, ?)}
    </select>
   </mapper>    

并从程序调用:

SqlSession session = sqlSessionFactory.openSession();
    Map<String, Object> eventInputMap = new HashMap<String, Object>();
        try {       
            EventDao ed = session.getMapper(EventDao.class);            
            eventInputMap.put("pnNetworkId", networkId);
            eventInputMap.put("pvUserIdentityId", identityId);          
            eventInputMap.put("success", 0);
            eventInputMap.put("message", null);         
            ed.getEvents(eventInputMap);
            session.selectList("EventDao.getEvents", eventInputMap);    
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            session.close();
        }

提前致谢!

【问题讨论】:

    标签: stored-procedures resultset mybatis multipleoutputs


    【解决方案1】:

    提供的代码有效。我什至检查了 3 种写法:比如这里有 parameterMap,没有 parameterMap(直接在语句中映射),通过注解,一切正常。

    我曾经认为 fetchSize 设置不会从主语句传播到 OUT 参数结果集,直到最近我真正测试了它。 要了解是否使用了 fetch size 以及它有多大的影响,结果必须包含足够多的行数。当然,最差的是从应用程序到数据库的延迟,效果更明显。 对于我的测试,过程使用的游标返回了 120 列的 5400 行(但最重要的是行数)。 为了给出一个数量级,我测量了获取时间,即从存储过程返回到语句返回,结果列表中填充了从游标中获取的数据。然后我记录第一个映射对象的实例化,这发生在全局获取开始附近,可能在第一次获取之后:

    public static boolean firstInstance = true;
    
    public Item() {
        if (firstInstance) {
            LOGGER.debug("Item first instance");
            firstInstance=false;
        }
    }
    

    我在结束时再次登录,在 session.selectList 返回之后。

    这仅用于测试目的。不要让它成为你的代码。找到一种干净的方法。

    这里有一些时间取决于配置的提取大小:

    - fetchSize=1    => 13000 ms
    - fetchSize=10   =>  5300 ms
    - fetchSize=100  =>  3800 ms
    - fetchSize=300  =>  3700 ms
    - fetchSize=500  =>  3650 ms
    - fetchSize=1000 =>  3600 ms
    

    Oracle JDBC 驱动默认 fetchSize 为 10。

    使用 fetchSize=1 进行测试可以证明使用了提供的设置。

    100,在这里,节省了 30%。除此之外,收益可以忽略不计(使用此用例和环境)

    无论如何,能够知道过程执行何时完成以及结果获取何时开始会很有趣。 不幸的是,Mybatis 的日志很少。我认为自定义结果处理程序可能会有所帮助,但查看类 org.apache.ibatis.executor.resultset.DefaultResultSetHandler 的源代码,我注意到 与允许使用自定义结果处理程序的方法 handleResultSet(用于简单的选择语句)不同,方法 handleRefCursorOutputParameter(在此用于过程 OUT 游标)不允许。然后无需尝试传递自定义结果处理程序:它将被忽略。 如果有人有解决方案,我对解决方案感兴趣。但似乎需要一个进化请求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-05
      • 2014-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-01
      • 2014-06-02
      • 2012-08-17
      相关资源
      最近更新 更多