5.7 mybatis之ResultHandler流式处理数据

文章目录


当一次性从数据库中查询大量数据时,由于结果集非常大,容易导致内存OOM,此时可以采用 分页查询或者可以利用 Mybatis 中的 ResultHandler 来实现流式输出,分页查询前面章节已经介绍过了,下面看下mybatis如何利用流式输出的,流式输出就像游标一样,一条条的处理目标结果集。

Mybatis 中的 ResultHandler 相当于数据结果集的处理器,它是一个回调函数(Callback),用来处理每一行数据的结果,这个回调函数可以在查询结果处理到一定量时触发,对结果集数据进行定制化处理。

ResultHandler 的使用可以大幅提升数据处理的效率,当我们需要处理大量的数据时,一般会使用 ResultHandler 来进行结果的处理,避免一次查询就全部返回结果,浪费内存资源或造成 OOM。

下面我们看下如何利用ResultHandler一条一条的数据处理

还是以下面的PERSON表为例
在这里插入图片描述
我们要查询persion_id大于多少的数据,对应的mapper文件如下所示

<resultMap id="resultMap1" type="com.lzj.bean.Person">
    <result column="PERSON_ID" property="id"></result>
    <result column="PERSON_NAME" property="name"></result>
    <result column="PERSON_AGE" property="age"></result>
</resultMap>
<select id="select1" resultMap="resultMap1">
    select * from PERSON where PERSON_ID > #{personId}
</select>

对应的Dao接口为

public interface PersonDao {
    public List<Person> select1(int personId);
}

下面重点来了,我们要定义自己的ResultHandler,用来定制化的处理每条数据,当然我们只是简单的输出每条数据

import com.lzj.bean.Person;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;

public class MyResultHandler implements ResultHandler<Person> {

    /*定制化处理每条数据,此处只是简单的输出*/
    @Override
    public void handleResult(ResultContext<? extends Person> resultContext) {
        Person person = resultContext.getResultObject();
        System.out.println(person);
    }
}

最后执行下面的测试案例

public void sqlSessionTest6(){
    SqlSessionFactory factory = mybatisUtil.getFactory();
    SqlSession sqlSession = factory.openSession(true);  //true表示自动提交
    sqlSession.select("com.lzj.dao.PersonDao.select1", 5, new MyResultHandler());
    sqlSession.close();
}

输出结果如下所示,从日志中可以看出,查出persion_id>5的数据总共有4条数据,分别通过我们定制的MyResultHandler的方法处理了每条数据。

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1114681666.
==>  Preparing: select * from PERSON where PERSON_ID > ? 
==> Parameters: 5(Integer)
<==    Columns: person_id, person_name, person_age
<==        Row: 6, Bob, 25
Person{id=6, name='Bob', age=25}
<==        Row: 7, Jimi, 24
Person{id=7, name='Jimi', age=24}
<==        Row: 8, Dobu, 40
Person{id=8, name='Dobu', age=40}
<==        Row: 9, Lee, 33
Person{id=9, name='Lee', age=33}
<==      Total: 4
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4270b142]
Returned connection 1114681666 to pool.
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一款优秀的ORM(Object Relational Mapping)框架,它提供了很多强大的功能,其中就包括流式查询。 流式查询是指在查询数据时,MyBatis会在每次查询时只加载一部分数据,而不是一次性将所有数据都加载到内存中,这样可以大大减少内存的使用,提高查询效率。同时,流式查询也可以很方便地处理大量数据,避免内存溢出等问题。 在MyBatis中,流式查询可以通过`selectList`方法的`ResultHandler`参数来实现。`ResultHandler`是一个回调接口,它会在每次查询时被调用,可以处理查询结果集中的每一行数据。 ```java SqlSession sqlSession = sqlSessionFactory.openSession(); try { sqlSession.select("selectUsers", new ResultHandler<User>() { @Override public void handleResult(ResultContext<? extends User> resultContext) { // 处理每一行数据 User user = resultContext.getResultObject(); // ... } }); } finally { sqlSession.close(); } ``` 需要注意的是,在流式查询中,由于每次查询只加载一部分数据,因此在处理完每一行数据后,需要将其从内存中清除,以避免内存溢出问题。可以通过`ResultContext`的`stop`方法来判断是否已经加载完所有数据。 ```java @Override public void handleResult(ResultContext<? extends User> resultContext) { // 处理每一行数据 User user = resultContext.getResultObject(); // ... // 判断是否加载完所有数据 if (resultContext.isStopped()) { // 加载完所有数据,结束查询 return; } // 清除内存中的数据 resultContext.next(); } ``` 使用流式查询可以很方便地处理大量数据,同时避免内存溢出等问题,但也需要注意正确地处理每一行数据和及时清除内存中的数据

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值