Lazy fetching in MyBatis

一笑奈何 提交于 2020-01-16 19:34:06

问题


I couldn't able to find how to achieve lazy loading(even in MyBatis docs).

My mapper xml is shown below:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.FooMyBatisLazyFetch">
        <select id="callFooProc"
                parameterType="com.example.FooProcBundle"
                statementType="CALLABLE">
            {call FooProc(
                    #{arg1,  jdbcType=VARCHAR, mode=IN},
                    #{arg2,  jdbcType=VARCHAR, mode=IN},
                    #{arg3,  jdbcType=VARCHAR, mode=IN},
                    #{error, jdbcType=NUMERIC, mode=OUT},
                    #{res2,  jdbcType=CURSOR,  mode=OUT, resultMap=FooProcResult}
                )
            }
        </select>

        <resultMap id="FooProcResult" type="com.example.FooProcResult">
            <result property="bar1" column="barcol1"/>
            <result property="bar2" column="barcol2"/>
            <result property="bar3" column="barcol3"/>
            <result property="bar4" column="barcol4"/>
            <result property="bar5" column="barcol5"/>
        </resultMap>
    </mapper>

Pojo Class:

    public class FooProcResult {
        private String bar1;
        private String bar2;
        private String bar3;
        private String bar4;
        private String bar5;
    }        

    public class FooProcBoondle {
        private String arg1;
        private String arg2;
        private String arg3;
        private Integer error;
        private List<FooProcResult> res2;
        //getters,setters, etc
    }

And usage code;

    FooProcBundle bundle = new FooProcBundle();
    bundle.setArg1("foo");
    bundle.setArg2("bar");
    bundle.setArg3("baz");
    fooMyBatisLazyFetch.callFooProc(bundle);
    Integer error = bundle.getError();
    if(error == 123) /*some condition*/ {
        List<FooProcResult> res2 = bundle.getRes2();
        // iterate res2
    --->// Only here CURSOR may be opened and executed
    }

i.e. I don't want to fetch res2 unless my code explicitly request for it. That particular cursor is quite heavy, and I don't want to execute it when it's not required(but mybatis does it).

Also I want to apply this to generator-like procedures (Oracle call them "Pipelined Table Functions" they yield result, sleep and wait until caller fetches next row - wakeup and calculate next. Usually they called this way: SELECT * FROM TABLE(GenProc(arg1,arg2)).

Any ideas about the configuration required to achieve this?


回答1:


Procedure output cursor parameters are processed in class org.apache.ibatis.executor.resultset.DefaultResultSetHandler in method handleOutputParameters and then in method handleRefCursorOutputParameter. You will note that the code in its current state, does not allow to do want you seek, the only "custom option" used is the resultMap that must be provided. I also would have appreciated some more options just like lazy loading, custom result handler, and some logs to be able to monitor the actual execution time and the fetch time.

This could be achieved in JDBC and would require configuration that is not implemented in the framework.



来源:https://stackoverflow.com/questions/37386083/lazy-fetching-in-mybatis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!