java - 试图理解为什么 @transactional(noROllBackFor .... 不起作用

标签 java spring jpa transactions

我有一些代码,如下所示:

@Transactional(noRollbackFor = { CannotAcquireLockException.class, LockAcquisitionException.class })
public void deleteSomeData() {
    int backOffTime = 0;
    int fibonacci = 1;
    boolean executed = false;

    do {
        try {
            this.myDAO.deleteTheData();
            executed = true;
        } catch (RuntimeException rt) {
            int newBackoffTime = backOffTime + fibonacci;
            fibonacci = backOffTime;
            backOffTime = newBackoffTime;
            try {
                Thread.sleep(backOffTime * 100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    } while (!executed);
}

它在 Spring/JPA 环境中运行。该代码由许多 Quartz 驱动的任务运行,这些任务在不同的时间触发,有时甚至同时触发。因此,如果抛出死锁异常,我试图通过在延迟后重新执行更新代码来解决数据库(MySQL)死锁问题。

我一直在尝试各种事情并阅读大量有关事务、死锁等的帖子。

问题是,如果 this.myDAO.deleteTheData(); 抛出 CannotAcquireLockException 则事务被标记为需要回滚。我试图做的是等待一段时间,然后再次尝试更新。然而,第二次尝试由于回滚状态而失败。因此,如果抛出此异常,我会尝试停止将事务设置为需要回滚。

我不确定我脑子里的所有这些都正确,并且这段代码不起作用。该事务仍被标记为需要回滚。

我可以将循环代码移到调用此方法的代码中,这将消除担心事务的需要,但是这将涉及大量的重复代码执行,我希望将其保持在附近尽可能到数据库。

关于我在哪里出错的任何建议?

最佳答案

阅读原始帖子中的答案后,我改用 Spring Retry并能够删除我所有的循环代码。该方法现在如下所示:

@Transactional
@ConcurrentDBUpdateRetryPolicy
public void deleteSomeData() {
    this.myDAO.deleteTheData();
}

使用自定义注释定义我想要采用的重试策略。您不需要执行自定义注释,但这样做可以让您集中公共(public)重试定义。这是自定义注释:

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Retryable(
   include = CannotAcquireLockException.class, 
   maxAttempts = 10, 
   backoff = @Backoff(delay = 500, maxDelay = 10000, multiplier = 2, random = true)
)
public @interface ConcurrentDBUpdateRetryPolicy {}

到目前为止,一切进展顺利。感谢提出建议的人,也感谢 Spring Retry 的作者。

关于java - 试图理解为什么 @transactional(noROllBackFor .... 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30368181/

相关文章:

java - 如何暂停所有正在运行的线程?然后恢复?

java - GZIPInputStream 的工作原理

java - JPA:自己的注释来为具有相同值的字段捆绑注释

Java 文件传输客户端不读取所有字节

java - SLF4J:SimpleLogger 不记录跟踪和调试,也不记录异常

java - Spring 数据休息: Return One-To-Many-To-One as Many-To-Many relation

java - 使用 AnnotationConfigApplicationContext 时禁用 Spring 日志记录

java - spring-boot 和 ./config 目录

java - 无法在 Spring 中使用 JPA 保持多对一关系(改为添加新的父实体)

java - 我需要在 native 查询 Jpa 中使用 @RequestParam 在后端级别对数据进行排序