JPA 存储库和阻塞 I/O

我遇到一个问题,在使用 JpaRepository 写入数据库后,我需要在单独的线程上执行几个慢速 HTTP 请求。问题是doActualJob()在等待一系列期货解决时的阻塞。这似乎可以防止底层 Hibernate 会话关闭,从而导致应用程序很快用完连接。


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


@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);

}


MMTTMM
浏览 94回答 2
2回答

慕斯王

嗯——非阻塞数据库 IO 在 Java/JDBC 世界中以标准方式是不可能的。简而言之——你的 Spring 数据存储库最终将使用 JPA ORM 实现(比如 Hibernate),而 JPA ORM 实现又将使用 JDBC 与之交互本质上是阻塞的数据库。Oracle(异步数据库访问 API )目前正在做这方面的工作,以提供与 JDBC 类似但非阻塞的 API。他们打算将此作为标准提出。Spring 人员在这方面也有一项令人兴奋的并行工作,即R2DBC – 反应式关系数据库连接。他们实际上也将其与 Spring 数据集成(链接) 这样可以帮助您集成到您的解决方案中。可以在此处找到 Spring 的一个很好的教程。

吃鸡游戏

我建议使用单独的JTA 事务写入数据库。这样做,定义一个像这样的方法@Transactional(Transactional.TxType.REQUIRES_NEW)public void saveJobStart(final long someJobId) {    SomeJob someJob = mSomeJobRepository.findOne(someJobId);    someJob.setJobStarted(Instant.now());    mSomeJobRepository.saveAndFlush(someJob);}当然不完全一样。如果doActualjob()失败,在您的情况下,数据库将不会保留开始日期。在我的提议中,它会坚持下去。作为补偿,您需要在新事务中删除doSlowJobcatch中的bloc 中的开始日期,然后重新处理异常。 throw
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java