MyBatis将ResultSet上的fetch大小设置为过程的out参数



我有需要使用MyBatis调用的存储过程。无论如何,我设法调用了这个存储过程。过程具有多个out参数。其中一个参数是oracle游标。我需要对Oracle Cursor进行迭代,但当我在没有使用fetchSize属性对jdbc驱动程序进行任何微调的情况下进行迭代时,它会逐行进行,并且这个解决方案非常缓慢。我可以在过程调用中设置fethcSize属性:

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

但这一点帮助都没有。我认为这不起作用,因为有多个out参数——所以程序不知道这个获取大小应该应用在哪里——在哪个out参数上。有没有办法在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();
        }

提前感谢!

提供的代码可以正常工作。我甚至检查了3种编写方法:比如这里有parameterMap,没有parameterMap[/em>(直接在语句中映射),通过注释,一切都正常。

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

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

我在会话结束后再次登录。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.ibati.executor.resultset.DefaultResultSetHandler的源代码,我注意到与允许使用自定义结果处理程序的方法handleResultSet(用于简单的select语句)不同,方法handleRefCursorOutputParameter不允许(此处用于过程OUT游标)。然后无需尝试传递自定义结果处理程序:它将被忽略。如果有人有解决方案的话,我对它感兴趣。但这似乎需要一个进化的要求。

相关内容

  • 没有找到相关文章

最新更新