我有一个非常具体的场景,在执行查询期间,特别是在从db到结果集的取行过程中,我得到了一个OutOfMemoryError。
代码很简单,因为它:
public interface MyRepository extends Repository<MyEntity, Long> {
@EntityGraph(value = "MyBigEntityGraphToFetchAllCollections", type = EntityGraphType.FETCH)
@QueryHints({@QueryHint(name = "org.hibernate.readOnly", value = "true")})
MyEntity getOneById(Long id);
}
public class MyService {
...
public void someMethodCalledInLoop(Long id) {
try{
return repository.getOneById(id);
} catch (OutOfMemoryError error) {
// Here the connection is closed. How to reset Hikaricp?
System.gc();
return null;
}
}
}看起来奇怪的是,getOne消耗了所有内存,但是由于急切地获取了大约80个集合,由于行的乘法,有些情况是无法支持的。
我知道我可以选择懒散地加载集合,但我不想这样做。每次加载时点击数据库1+N次数会消耗更多的时间,而我的应用程序却没有它。它是一批处理每毫安的记录,少于0,001%的记录在内存中产生了这种影响。所以我的策略是丢弃这几个记录,然后处理下一个记录。
捕获OutOfMemoryError之后,内存就被释放了,麻烦实体就变成了垃圾。但是由于此错误,HikariCP关闭(或被迫关闭)连接。
在方法的下一个调用中,hikaricp仍然给我一个封闭的连接。似乎是由于内存不足,hikaricp没有正确完成以前的事务,并且永远停留在这种状态。
我现在的目的是重置或恢复hikaricp我不需要关心使用池的其他线程。
因此,毕竟,我的简单问题是,如何在不重新启动应用程序的情况下,以编程方式重新启动或恢复原始状态。
谢谢,非常感谢看过这个的人。
发布于 2020-09-18 23:06:57
到目前为止,一切都不起作用。
我通过向该方法添加一个“查询提示”来最小化这个问题:
@QueryHints({@QueryHint(name = "org.hibernate.timeout", value = "10")})
MyEntity getOneById(Long id);99%的结果集是在1秒或更短的时间内获取的,但有时结果集太大,花费的时间更长。这样,JDBC就会在内存受损之前停止获取结果。
发布于 2020-08-27 17:06:50
尝试将其添加到Hibernate配置中:
<property name="hibernate.hikari.connectionTestQuery">select 1</property>这样,HikariCP将在将连接交给Hibernate之前测试连接是否仍然处于活动状态。
https://stackoverflow.com/questions/63620701
复制相似问题