【发布时间】:2021-04-21 14:10:40
【问题描述】:
如果我从 spring-retry 库中添加 @Retryable,我将无法在事务中执行数据库操作。这是我的代码结构的样子:
public class ExpireAndSaveTrades {
@Transactional(rollbackFor = MyException.class)
public void expireAndSaveTrades(List<Trade> trades) {
try {
// these two MUST be executed in one transaction
trades.forEach(trade -> dao.expireTrades(trade));
dao.saveTrades(trades);
} catch (Exception e) {
throw new MyException(e.getMessage(), e);
}
}
}
public class Dao {
@Retryable(value = CannotAcquireLockException.class,
maxAttempts = 3,
stateful = true,
backoff = @Backoff(delay = 300, multiplier = 3))
public void expireTrades(Trade trade) {
try {
tradeRepository.expire(trade.getId(), trade.getNewStopDate());
} catch (CannotAcquireLockException e) {
expireTrade(trade);
}
}
@Retryable(value = CannotAcquireLockException.class,
maxAttempts = 3,
stateful = true,
backoff = @Backoff(delay = 300, multiplier = 3))
public void saveTrades(List<Trades> trades) {
try {
tradeRepository.saveAll(trades)
} catch (CannotAcquireLockException e) {
saveTrades(trades);
}
}
}
public interface TradeRepository extends JpaRepository<Trade, Integer> {
@Modifying
@Query(value = "update trade set stop_date=:new_stop_date where id=:id", nativeQuery = true)
void expire(@Param("id") int id, @Param("new_stop_date") String newStopDate);
}
所以这就是我现在的位置:
- 不使用有状态(即有状态默认设置为
false) - 重试成功,但在它结束时,我看到这个异常:org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only并且多次重试后更新/保存的数据是在数据库表中回滚 - stateful = true - 不再发生重试
我浏览了许多 SO 帖子和博客,但找不到解决问题的方法。有人可以帮帮我吗?
编辑: 更新了我的问题以添加 try-catch 块这样,spring-retry 不会启动(我知道,因为我添加了一个侦听器到 @Retryable 以记录 retryContext .我没有看到日志被打印出来。如果有一个CannotAcquireLockException,事务也会默默地回滚
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
LOGGER.info("Retry Context - {}", context);
}
【问题讨论】:
-
请用以下内容更新问题: 1.
ExpireAndSaveTrades类与它有何关联。 2.Daoclass'方法里面到底发生了什么(如果有其他类的调用,也请贴出来) -
@amseager - 更新了问题,我正在使用 spring-data 进行数据库操作
-
谢谢@crizzis - 我确实看过这篇文章..但我无法让它工作。让我再试试看
-
使用有状态重试,只维护状态;您必须调用该方法,直到成功或重试用尽;看我的回答。
标签: java spring transactions spring-transactions spring-retry