JPA 存储库和阻塞 I/O

Mat*_*son 4 java spring-data-jpa spring-boot

我遇到一个问题,在使用 JpaRepository 写入数据库后,我需要在单独的线程上执行多个缓慢的 HTTP 请求。问题是doActualJob()在等待一系列 future 解决时会发生阻塞。这似乎阻止了底层 Hibernate 会话关闭,导致应用程序很快耗尽连接。

如何编写此函数,以便在执行阻塞 I/O 时数据库连接不保持打开状态?是否可以使用 JpaRepositories,或者我是否需要使用较低级别的 API(如 EntityManager/SessionFactory)?

@Service
class SomeJobRunner {

    private final SomeJobRepository mSomeJobRepository; //extends JpaRepository

    @AutoWired
    public SomeJobRunner(final SomeJobRepository someJobRepository) {
        mSomeJobRepository = someJobRepository;
    }

    @Async
    public void doSlowJob(final long someJobId) {
        SomeJob someJob = mSomeJobRepository.findOne(someJobId);
        someJob.setJobStarted(Instant.now());
        mSomeJobRepository.saveAndFlush(someJob);

        doActualjob(); // Synchronous job doing several requests using Unirest in series

        someJob = mSomeJobRepository.findOne(someJobId);
        someJob.setJobEnded(Instant.now());
        mSomeJobRepository.saveAndFlush(someJob);
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*dra 7

嗯 - 非阻塞数据库 IO 在 Java/JDBC 世界中以标准方式是不可能的。简单地说 - 你的 Spring 数据存储库最终将使用 JPA ORM 实现(如 Hibernate),而 JPA ORM 实现又将使用 JDBC 进行交互数据库本质上是阻塞的。Oracle 目前正在做这方面的工作(异步数据库访问 API),以提供与 JDBC 类似但非阻塞的 API。他们打算将此作为标准提出。Spring 人员在R2DBC \xe2\x80\x93 Reactive Relational Database Connectivity上也做出了令人兴奋的并行努力。他们实际上也将其与 Spring 数据集成(链接),以便可以帮助您集成到您的解决方案中。Spring 对此的一个很好的教程可以在这里找到

\n

编辑:从 2022 年起 Hibernate也有响应式选项

\n