gpt4 book ai didi

java - 在内部服务中捕获 AccessDeniedException 时防止事务回滚

转载 作者:行者123 更新时间:2023-11-29 02:58:16 25 4
gpt4 key购买 nike

我有 2 个服务:RecentRecordServiceBookService

@Service
public class RecentRecordService {
@Transactional
public List<Book> getRecentReadBooks() {
List<Long> recentReadBookIds = getRecentReadBookIds();
List<Book> recentReadBooks = new ArrayList<>();

for (Long bookId : recentReadBookIds) {
try {
Book book = bookService.getBook(bookId);
recentReadBooks.add(book);
} catch (AccessDeniedException e) {
// skip
}
}

return recentReadBooks;
}
}
@Service
public class BookService {
@Transactional
public Book getBook(Long bookId) {
Book book = bookDao.get(bookId);
if (!hasReadPermission(book)) {
throw new AccessDeniedException(); // spring-security exception
}
return book;
}
}

假设 getRecentReadBookIds() 返回 [1, 2, 3]

当 session 用户拥有从 getRecentReadBookIds() 返回的所有图书 ID 的权限时,一切正常。 getRecentReadBooks() 将返回 3 个 Book 的列表。

突然,#2 书的所有者将其权限设置从“公开”更改为“私有(private)”。因此, session 用户无法再阅读第 2 本书。

我原以为 getRecentReadBooks() 会返回 2 个 Book 的列表,其中包含第 1 本书和第 3 本书的信息。但是,该方法失败并出现以下异常:

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

经过一些研究,我发现它与事务传播有关。即使我使用 try-catch 处理 getRecentReadBooks() 中的 AccessDeniedException,事务也会被标记为“仅回滚”。

这个问题似乎可以通过将 getBook()@Transactional 注释更改为:

    @Transactional(propagation = Propagation.NESTED)
public Book getBook(Long bookId) {
// ...
}

    @Transactional(noRollbackFor = AccessDeniedException.class)
public Book getBook(Long bookId) {
// ...
}

但是,我想知道只修改RecentRecordService是否可以解决问题。毕竟,RecentRecordService 是想要自行处理 AccessDeniedException 的服务。

任何建议都会有所帮助。谢谢。

最佳答案

我认为只修改RecentRecordService 是不可能解决这个问题的,因为交易已经在BookService 中被标记为回滚了 RuntimeException 发生在其中。一旦 TransactionStatus 被标记为 rollback ,就没有办法将其恢复为当前不回滚。

因此,您必须通过以下方式使 BookService#getBook() 不将事务标记为回滚:

@Transactional(noRollbackFor = Throwable.class)
public Book getBook(Long bookId) {

}

这意味着无论发生什么异常,事务都不会被标记为回滚。这样做是有意义的,因为这个方法应该是只读的,所以当一个方法不应该修改任何东西时回滚是没有意义的。

关于java - 在内部服务中捕获 AccessDeniedException 时防止事务回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59412942/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com