缓存是个好东西,可以提高访问速度,也可以做中间过渡层。

之前同事写excel导入,数据量几千行左右,但是硬是内存溢出了。最后定位到为jpa缓存问题。jpa的缓存有两种,一种是一级缓存,也就是session级别的缓存,另一个是二级缓存是全局缓存。当执行findOne方法的时候先到一级缓存中找,如果没找到再到二级缓存中找。缓存的设计,极大的提高了运行速度。

那么为什么会内存溢出呢?之前同事的代码是这样写的。

Integer count = 0;
List<UserModel> userList = new ArrayList<UserModel>();
//…
if (count == 2000) {
userRepository.save(userList);
count=0;
}

中间就是解析excel 并添加到集合里面去,每加一条就把count加一,如果count等于2000,就保存一下,然后把count置零。代码看起来没有什么问题, 但是线上就是因为这段代码导致内存溢出。

原因是,jpa在保存的时候,并不是直接保存到数据库,而是存放到缓存里。等到方法结束的时候才把缓存的数据刷到数据库

那么解决这个问题就有两个方法 执行 flush,手动把缓存刷到数据库。

手动刷新到数据库很简单

userRepository.saveAndFlush(user)

 

只需要把save方法换成saveAndFlush方法。saveAndFlush方法的源码

public <S extends T> S saveAndFlush(S entity) {

    S result = save(entity);
    flush();

    return result;
}</pre>

其实内部就是调用了save方法,然后调用了flush方法。