一、流式查询
关于流式查询的内容在这篇文章里面
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>
两种方法的插入时间分别为
测试数据插入一万条数据,时间的差别是十分明显的。