使用 Spring 时如何手动取消 JPA 或 Hibernate 事务

Mak*_*khz 4 java spring hibernate jpa transactions

我正在使用 JPA 2 Hibernate 实现和 Spring MVC 来管理事务

我正在使用通用 DAO 模式来管理数据库操作

目前,我们有一个单一方法的事务,例如:

someDao.save (someObject)
Run Code Online (Sandbox Code Playgroud)

它是@Transactional从 JSF 页面调用的方法。

save方法继承自Generic DAO,它以级联oneToMany关系持久化到数据库中的多个实体,但是它要在数据库中执行大约1000条insert语句,因此需要很长的时间。

我想为用户提供一种取消操作的方法,但到目前为止,我无法做到这一点,当我调用方法 save() 时,它无法取消,直到所有插入都已执行。

我尝试抛出一些异常,从注入的 PersistenceContext 回滚事务,但它没有用,它只是完成而没有错误:(

显然,我不能从方法内抛出异常,这只是来自我的源的一次调用。JPA PersistenceContext 做所有事情

有没有办法取消操作并强制回滚?

Vla*_*cea 5

保存 1000 个实体应该不会花那么长时间。确保您从JDBC 批处理中受益:

  1. 您需要使用不是 IDENTITY 的实体标识符。IDENTITY 禁用批处理。SEQUENCE 和 TABLE 生成器允许批处理。
  2. 设置以下休眠属性:

    <property name="hibernate.order_updates" value="true"/>
    <property name="hibernate.order_inserts" value="true"/>
    <property name="hibernate.jdbc.batch_versioned_data" value="true"/>
    <property name="hibernate.jdbc.fetch_size" value="50"/>
    <property name="hibernate.jdbc.batch_size" value="520"/>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果您想使保存操作超时,您需要使用以下方式注释您的服务方法:

这样,30 秒后,您的保存事务将超时并抛出异常,回滚所有插入。


批量处理

如果您想取消批量插入操作,同时允许已处理的项目继续进行,那么您需要选择批量处理。

您需要将所有项目拆分成块并批量插入。为此,我将从实际的批处理线程中分离批处理开始和批处理结束边界。因此,虽然批处理开始和批处理结束是由 Web 请求触发的,但批处理是由专用的ExecutorService运行的。

这样您就可以:

由于查询执行是I/O阻塞操作,因此需要支持线程中断,以便当批处理结束线程中断批处理执行器时,可以通知您停止处理下一批并尽快退出。

我会使用单独的 ExecutionService