Mybatis流式查询(查询数据过大的处理)

Mybatis流式查询(查询数据过大的处理)

问题:

在我们的应用场景中,可能会遇到查询返回的数据为上千万条的情况。如果不处理的话,数据太多可能会爆掉内存,而如果用分页的方式接收的话,可能会受数据库结构限制,降低一些效率。

流式查询

因此,所以有了流式查询的概念。流式查询返回的数据不是一个集合、List,而是一个迭代器,我们通过从迭代器中每次取出一条数据,从而对返回的数据进行处理,进而节约内存,而流式查询的这个特性又决定了,在执行流式查询的过程中,与数据库必须保持连接状态。

使用

接口类:org.apache.ibatis.cursor.Cursor

Mapper方法:

@Mapper
public interface TestMapper {
    @Select("select * from test limit #{limit}")
    Cursor<Test> scan(@Param("limit") int limit);
}

在mapper,我们只需要指定返回值类型为Cursor,就实现了一个流式查询

Controller:

@GetMapping("test/scan/3/{limit}")
@Transactional
public void scanTest3(@PathVariable("limit") int limit) throws Exception {
    try (Cursor<> cursor = testMapper.scan(limit)) {
        cursor.forEach(test -> { });
    }
}

在Controller中,如果我们要使用这个方法,首先要解决数据库持续连接的问题,因为默认mapper方法在执行之后会关闭数据库连接,所以在使用的时候需要加注解 @Transactional 。这样就实现了一个流式查询过程。当然还有其他方法能够维持数据库的持续连接状态,如:

额外方法一:
try (
        SqlSession sqlSession = sqlSessionFactory.openSession();  // 1
        Cursor<> cursor =
              sqlSession.getMapper(TestMapper.class).scan(limit)   // 2
    ) {
        cursor.forEach(test -> { });
    }
额外方法二:
TransactionTemplate transactionTemplate =
            new TransactionTemplate(transactionManager);  // 1

    transactionTemplate.execute(status -> {               // 2
        try (Cursor<Test> cursor = testMapper.scan(limit)) {
            cursor.forEach(test -> { });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    });

后面两者实现起来都没有注解方便,当然在使用的注解的时候,一定要记得,注解只能在外部调用时起作用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值