Java Spring数据-乐观重试机制工作不正常

Java Spring数据-乐观重试机制工作不正常,java,spring,aop,aspectj,optimistic-locking,Java,Spring,Aop,Aspectj,Optimistic Locking,我的一个服务中包含以下代码: @Override @Transactional @RetryConcurrentOperation(exception = Exception.class, retries = 12) public void test() { Player player = this.playerRepository.findPlayerById(1L); player.setFirstName("SomeName"); } 我使用的重试机制如下所述: 问题是,当我得到乐观

我的一个服务中包含以下代码:

@Override
@Transactional
@RetryConcurrentOperation(exception = Exception.class, retries = 12)
public void test() {

Player player = this.playerRepository.findPlayerById(1L);
player.setFirstName("SomeName");
}
我使用的重试机制如下所述:

问题是,当我得到乐观重试(第二次重试)时,我得到一个异常:

Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [xxx]
有趣的是,当我删除事务性注释,并且在非事务性函数中调用不同的事务性方法时,该机制会起作用:

// THIS WORKS: 
@Override
@RetryConcurrentOperation(exception = Exception.class, retries = 12)
public void test() {
 execute();

}   

@Override
@Transactional
public void execute() {
Player player = this.playerRepository.findPlayerById(1L);
player.setFirstName("SomeName");
}

你知道为什么这个方面重试机制在从事务函数调用时没有成功吗?

当从非事务性的
test()
调用
执行()时,将不应用
执行()
中的
@transactional
。这是因为它是从对象的一个方法直接到另一个方法的直接调用,它绕过了事务代理

有关代理如何工作以及使用
this
调用事务函数时
@Transactional
为何不工作的更多详细信息,请参见此

还可以看看Spring,它是针对这个问题的基于Spring的解决方案

关于重试机制,它不适用于正在使用版本化实体(具有
@Version
列)的情况,这是在抛出
StaleObjectStateException
的情况下

原因是有另一个线程正在更新数据库中的实体,从而增加版本列


解决方案是
刷新()
实体(加载最新版本),重新应用修改并重试。重试几次相同的修改只会在未版本化的实体中起作用,这可能不是您想要的,因为一个线程所做的更改会被另一个线程悄悄地覆盖。

看来RetryTemplat不是通用的。每次我想要重试时,我都需要实现一个特殊的回调函数。回调允许应用一些恢复逻辑(例如写入另一个表,记录日志表中的异常等)。在没有@Transactional的情况下在数据库中触发更新/插入?我已经添加了为什么我认为@Transactional不被应用,这是一个绕过代理的reetrant调用。同样,对于版本化实体(这里的例子),博客文章中的策略也不起作用,请参见上面的更新答案,最后@Transactional在这些情况下起作用了吗?我认为有两个问题,一个是事务性调用不适用于可重入调用,另一个是博客帖子不适用于版本化实体,这是您要寻找的答案,还是其他问题?尝试以下解决方案: