在 OutOfMemoryError 后恢复 Hikaricp

Recover Hikaricp after OutOfMemoryError

我有一个非常具体的场景,在执行查询期间,特别是在从数据库中获取行到我的结果集期间,我得到一个 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。我不需要关心使用池的其他线程。

所以,毕竟,我的简单问题是,如何在不重启应用程序的情况下以编程方式重启或恢复 hikarycp 到其主要状态。

非常感谢阅读本文的人。

尝试将此添加到您的 Hibernate 配置中:

<property name="hibernate.hikari.connectionTestQuery">select 1</property>

这样 HikariCP 将在将连接提供给 Hibernate 之前测试连接是否仍然存在。

到目前为止没有任何效果。

我通过在方法中添加 'query hint' 来最小化问题:

@QueryHints({@QueryHint(name = "org.hibernate.timeout", value = "10")})
MyEntity getOneById(Long id);

99% 的结果集在 1 秒或更短的时间内获取,但有时结果集太大,需要更长的时间。这样 JDBC 在内存受到损害之前停止获取结果。