如果添加 @Retryable
从spring库。我的代码结构是这样的:
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);
}
我现在的处境是:
不使用stateful(即stateful设置为 false
默认情况下)-重试成功,但在结束时,我看到以下异常: org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
并且多次重试后更新/保存的数据回滚到数据库表中
stateful=true-重试不再发生
我浏览了很多帖子和博客,但都找不到解决问题的方法。这里有人能帮我吗?
编辑:更新了我的问题,添加了try-catch块,这个spring重试不起作用(我知道是因为我添加了一个侦听器) @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条答案
按热度按时间krugob8w1#
您正在事务中重试;这是错误的,会产生你所看到的结果;您需要交换它并在重试中执行事务。这就是为什么在不使用stateful时会出现回滚错误。
如果使用有状态重试,则
@Retryable
不属于保留状态;retryable的调用者必须一直调用,直到成功或重试。编辑
下面是一个使用有状态重试的示例
而且,如果没有
@Recover
方法。。。