使用mybatis游标的目的是,避免百万级以上的数据到jvm,造成内存溢出
但是初次使用游标不一定能够正确使用
下面就给出两种不同的方式,对比一下
1.错误使用方式
-
设置堆内存最大值,方便观察jvm内存使用情况
-
代码如下:
mapper.java@Select("SELECT * FROM user_detail") Cursor<UserDetail> getFakeCursor();
Test.java
@Test public void getFakeCursorTest() { Cursor<UserDetail> cursor = userMapper.getFakeCursor(); for (UserDetail userDetail : cursor) { log.info(userDetail.toString()); } }
-
通过VisualVM观察jvm内存使用情况
可以看出只用了14s的时间jvm内存就被耗尽了,CUP的使用率也很高
- 最后造成内存溢出错误
- 通过源码调试发现resutSet包含的属性是ResultRowsStatic
2.正确使用方式
- 代码如下:
mapper.java
/**
*
* 实现了mysql数据的流式读取
*
* fetchSize = Integer.MIN_VALUE 必须这样设置才可以获取到真正的游标
*
* @return
*/
@Select("select * from user_detail")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE)
@ResultType(UserDetail.class)
Cursor<UserDetail> getRealCursor();
Test.java
@Test
public void getRealCursorTest() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Cursor<UserDetail> cursor = mapper.getRealCursor();
assertFalse(cursor.isOpen());
for (UserDetail userDetail : cursor) {
log.info(userDetail.toString());
}
}
}
- 通过VisualVM观察jvm内存使用情况
内存和CPU使用情况恢复正常
- 通过源码调试发现resutSet包含的属性是ResultRowsStreaming
- 示例代码github地址
更多推荐
正确使用mybatis游标
发布评论