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

标签 java spring hibernate jpa transactions

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

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

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

someDao.save (someObject)

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

save方法继承自Generic DAO,它持久化了多个实体的数据库,具有级联的oneToMany关系,但是它要在数据库中执行几千条插入语句,所以耗时很长。

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

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

显然,我不能从方法中抛出异常,它只是来 self 的源的一次调用。 JPA PersistenceContext 做一切

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

最佳答案

保存 1000 个实体应该不会花那么长时间。确保您受益于 JDBC batching :

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

    <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"/>
    
  3. 如果你想让保存操作超时,你需要在你的服务方法中添加注释:

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


批处理

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

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

这样你就可以:

  • 同时处理批处理
  • 立即停止所有批处理,使用shutdownNow

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

我会使用一个单独的 ExecutionService

关于java - 使用 Spring 时如何手动取消 JPA 或 Hibernate 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25633085/

相关文章:

java - 首次登录 : HTTP Status 500 - Request processing failed; nested exception is org. springframework.transaction.CannotCreateTransactionException

java - 如何让 Play 在与现有对象合并时创建新的 ID(自动增量)

java - 时间线通知上的空响应

java - 构造函数的参数 0 需要一个无法找到的 bean

hibernate - 为什么类元空间在 Java 8 中会随着时间的推移而增加?

spring - Elasticsearch Spring数据-文档注释中的动态indexName

java - Spring Boot 中的 CORS 不起作用 - 得到空响应

java - 从文件属性中检索标签列表

java - 在 java 中填充数字直到字符串长度为 8 个字符?

java - 为什么我们应该在 Java 中使我们的 POJO 可序列化?