joh*_*inp 5 java spring hibernate spring-transactions
我有 2 项服务:RecentRecordService和BookService 。
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
假设getRecentReadBookIds()返回[1, 2, 3].
当会话用户拥有从 返回的所有图书 ID 的权限时getRecentReadBookIds(),一切正常。getRecentReadBooks()将返回 3 的列表Book。
突然,#2 书的所有者将其权限设置从“公共”更改为“私人”。因此,会话用户无法再阅读#2 本书。
我期望它getRecentReadBooks()会返回一个 2 的列表Book,其中包含书 #1 和书 #3 的信息。但是,该方法失败,但出现以下异常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
Run Code Online (Sandbox Code Playgroud)
经过一番研究,我发现这和交易传播有关系。即使我使用 try-catch 来处理 in ,该转换也会被标记为“仅回滚AccessDeniedException” getRecentReadBooks()。
这个问题似乎可以通过将@Transactional注释更改为getBook()来解决:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
Run Code Online (Sandbox Code Playgroud)
或者
@Transactional(noRollbackFor = AccessDeniedException.class)
public Book getBook(Long bookId) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
但是我想知道是否可以通过仅修改RecentRecordService. 毕竟是想要自己RecentRecordService处理的人。AccessDeniedException
任何建议都会有所帮助。谢谢。
引用自文档
默认情况下,事务将在 RuntimeException 和 Error 上回滚,但不会在已检查异常(业务异常)上回滚
AccessDeniedException是 RuntimeException 的子类
如果在您的情况下使用的 AccessDeniedException 是 spring 框架,并且根据要求,如果拒绝访问的异常可以设为自定义业务异常(不是 Runtime Exception 的子类),则它应该无需注释 getBook(Long bookId) 方法即可工作。
更新
OP 决定解决根本原因。这是为了提供我的答案背后的基本原理,以供将来参考
AccessDeniedException :如果 Authentication 对象不拥有所需的权限,则抛出该异常。
根据我的理解,这里对书籍的访问是基于业务逻辑而不是特定于用户角色。自定义业务异常适合这种情况。
| 归档时间: |
|
| 查看次数: |
1991 次 |
| 最近记录: |