mybatis_流式查询 Cursor 和 foreach 批量插入

一、流式查询

关于流式查询的内容在这篇文章里面

https://mp.weixin.qq.com/s/LtXPdM9OOSlGypqCd5Asmw

流式查询 cursor 就是让查询的速度加快。其使用也很简单,使用

org.apache.ibatis.cursor.Cursor

就可以了,具体的使用如下,比如普通的查询

@Select("select * from book limit #{limit}")
List<BookEntity> listBooksNormal(@Param("limit") Integer limit);

使用流式查询的话就改成

@Select("select * from book limit #{limit}")
Cursor<BookEntity> listBooks(@Param("limit") Integer limit);

其查询的效率明显提升,测试查询3000条数据,两种方法的时间分别为
在这里插入图片描述
但是使用流式查询的话,有一点是需要注意的,因为mybatis的查询是自动会把数据库连接关闭的,而使用流式查询的话是需要保持数据库一直连接。
根据上文文章的内容有三点解决方案

第一种:SqlSessionFactory

try (
        SqlSession sqlSession = sqlSessionFactory.openSession();  // 1
        Cursor<Foo> cursor =
              sqlSession.getMapper(FooMapper.class).scan(limit)   // 2
    ) {
        cursor.forEach(foo -> { });
    }

第二种:TransactionTemplate

TransactionTemplate transactionTemplate =
            new TransactionTemplate(transactionManager);  // 1

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

第三种:@Transactional

	@Transactional
    @Test
    void contextLoads() {
        Integer limit = 30000;

        LocalTime begin = LocalTime.now();
        List<BookEntity> bookEntities = bookService.listBooksNormal(limit);
        LocalTime end = LocalTime.now();
        Duration between = Duration.between(begin, end);
        System.out.println("-------------------------- 普通查询 " + between.toMillis() + "ms ------------------------------");

        // 流式查询
        LocalTime begin1 = LocalTime.now();
        Cursor<BookEntity> bookEntities1 = bookService.listBooks(limit);
        LocalTime end1 = LocalTime.now();
        Duration between1 = Duration.between(begin1, end1);
        System.out.println("-------------------------- 流式查询 " + between1.toMillis() + "ms ------------------------------");

    }

二、foreach 批量插入

在要使用流式查询的时候数据存入数据库。写了两种插入方法,第一种是一次插入一个,然后循环调用,这个是十分耗时的,因为一直调用操作数据库代码;第二种是批量插入,使用 foreach 语句插入,先把 sql 语句封装好,然后再调用操作数据库的语句。
第一种方法

System.out.println("----------------------普通插入--------------------------");
LocalTime begin = LocalTime.now();
for (int i1 = 0; i1 <= 10000; i1++) {
     bookService.addBook(bookEntity);
}
LocalTime end = LocalTime.now();
Duration between = Duration.between(begin, end);
System.out.println("-------------------------- " + between.toMillis() + "ms ------------------------------");

第二种方法

ArrayList<BookEntity> bookEntities = new ArrayList<>();
for (int i = 0; i <= 10000; i++) {
    bookEntities.add(bookEntity);
}
System.out.println("----------------------优化插入--------------------------");
LocalTime begin1 = LocalTime.now();
int i = bookService.addBooks(bookEntities);
LocalTime end1 = LocalTime.now();
Duration between1 = Duration.between(begin1, end1);
System.out.println("-------------------------- " + between1.toMillis() + "ms ------------------------------");

sql 代码

<insert id="addBooks" parameterType="java.util.List">
    INSERT INTO book (bookName,bookCounts,detail)
    VALUES
    <foreach collection="bookEntities" item="book" separator=",">
        (#{book.bookName},#{book.bookCounts},#{book.detail})
    </foreach>
</insert>

两种方法的插入时间分别为
在这里插入图片描述
测试数据插入一万条数据,时间的差别是十分明显的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值