Mybatis 3.4.0 Cursor的使用

96
Draft灬h
2016.11.21 12:42* 字数 279

在mybatis 3.4.0版本中新增了一个功能,查询可以返回Cusror<T>类型的数据,类似于JDBC里的ResultSet类,当查询百万级的数据的时候,使用游标可以节省内存的消耗,不需要一次性取出所有数据,可以进行逐条处理或逐条取出部分批量处理。

在使用方式上没有太大变化

mybatis单独使用

XML mapping :

<select id="getEmployeeNestedCursor" resultMap="results" resultOrdered="true">
       select id,name,salary,skill from employees order by id
</select>

Java code :

Cursor<Employee> employees = sqlSession.selectCursor("getEmployeeNestedCursor");

// Get an iterator on employees
Iterator<Employee> iter = employees.iterator();

List<Employee> smallChunk = new ArrayList(10);
while (iter.hasNext()) {
    // Fetch next 10 employees
    for(int i = 0; i<10 && iter.hasNext(); i++) {
        smallChunk.add(iter.next());
    }
    doSomethingWithAlreadyFetchedEmployees(smallChunk);
    smallChunk.clear();
}

在3.4.0版本中,不支持@select注解,在3.4.1版本中已经修复:

@select("select id,name,salary,skill from employees order by id")
public Cursor<Employee> getEmployeeNestedCursor();

==Cursor在session关闭的同时被关闭==

spring 整合mybatis的使用

在mybatis-spring的整合中,mybatis中sqlSession中由org.mybatis.spring.SqlSessionTemplate实现替代。sqlSession关闭是由SqlSessionTemplate管理,所以返回后的Cursor对象是已经被关闭了的,无法使用。

在mybatis-spring 1.3.0版本中新增加了MyBatisCursorItemReader类,需要spring-batch jar包的支持,通过MyBatisCursorItemReader我们可以对Cursor进行操作。

bean.xml

<bean id="myMyBatisCursorItemReader"  class="org.mybatis.spring.batch.MyBatisCursorItemReader">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        <property name="queryId" value=""/>
</bean>
  • queryId:使用Cursor的查询sql id。
try{
    Map<String,Object> paramsMap = new HashMap<>();
    //查询的sql所3需要的参数
    paramsMap.put("oredCriteria",transferExample.getOredCriteria());
    paramsMap.put("orderByClause",transferExample.getOrderByClause());
    //设置参数
    myMyBatisCursorItemReader.setParameterValues(paramsMap);
    //打开
    myMyBatisCursorItemReader.open(new ExecutionContext());
    List<Employee> smallChunk = new ArrayList(10);
    Employee employee;
    while ((employee=myMyBatisCursorItemReader.read())!=null) {
        // Fetch next 10 employees 
        for(int i = 0; i<10 && iter.hasNext(); i++) {
            smallChunk.add(iter.next());
        }
        doSomethingWithAlreadyFetchedEmployees(smallChunk);
        smallChunk.clear();
    }catch(Exception e){
        //do some
    }finally{
        myMyBatisCursorItemReader.close();
    }
}
Mybatis