java - JPA使用flush来触发异常并停止执行

标签 java multithreading jpa

在最近的任务中,在创建对象后,我将结果刷新到数据库。数据库表有一个唯一约束,这意味着如果我尝试第二次刷新同一条记录,我将得到 ConstraintViolationException 。示例片段如下所示:

createEntityAndFlush(result);
sendAsyncRequestToThirdSystem(param);

createEntityAndFlush 的代码:

private T createEntityAndFlush(final T entity) throws ServiceException {
    log.debug("Persisting {}", entity.getClass().getSimpleName());
    getEntityManager().persist(entity);
    getEntityManager().flush();
    return entity;
}

我使用flush的原因是我想确保ConstraintViolationException将在完成交易之前抛出,从而调用 sendAsyncRequestToThirdSystem 。但事实并非如此,因为 sendAsyncRequestToThirdSystem抛出异常后被调用。

为了在竞争条件下测试代码,我使用了 ManagedExecutorService 并创建了两个可运行的任务 (Future<?> submit(Runnable task))复制传入的请求。

最终,通过尝试为每个唯一的请求 id 在新表上执行锁定来解决问题,但我想知道我的第一种方法哪里错了(例如,错误使用闪存,ManagedExecutorService 负责尴尬的情况)行为)。提前致谢!

最佳答案

问题是,虽然 flush() 确实将更改刷新到数据库中,但事务仍然处于打开状态,并且在事务提交 (这可能取决于数据库,但至少对于 Postgres 和任何使用数据库的 MVCC 而言)。

因此,您需要确保 createEntityAndFlush(result); 在自己的事务中运行,可能使用 @Transactional(propagation = Propagation.REQUIRES_NEW) (或相当于,如果不使用 Spring)来查看是否违反了唯一索引。

关于java - JPA使用flush来触发异常并停止执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59900014/

相关文章:

java - 随机类表现奇怪?

java - 我应该在线程中声明变量还是在Android中创建一个全局变量?

java - 基于spring xml的bean定义, `bean`元素的类属性

java - 在 GET 方法中用于过滤对象的可选属性

java - Ubuntu下如何加载和使用Liberation字体

java - 如何从我的代码中删除 protected void Finalize() 方法

java - SSO 中的显式身份验证

c# - 了解 Thread/BeginInvoke? [初学者]

java - 线程在 Mule 1.3 中如何工作?

mysql - EclipseLink JPA 辅助服务器