在使用 spring data jpa 的 SpringBoot 中,默认配置(不更改任何内容),如果在我的服务层中,我调用给定存储库的 saveAll 方法,该存储库用 @Repository 注释,并且我有一个 catch 子句捕获 DataAccessException,我understand 涵盖了数据库可能出错的所有可能异常,由于@Transactional 注释,回滚是否仍会被触发?
例如:
存储库:
@Repository
public interface BookRepository extends JpaRepository<Book, Integer> {
}
服务:
@Service
public class BookService {
private final BookRepository bookRepository;
public BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
public void saveAllBooks(List<Book> books) {
try {
bookRepository.saveAll(books);
} catch (DataAccessException e) {
// notify external service about failure
// log exception
}
}
}
如果我这样做,回滚仍然会发生还是我需要重新抛出异常?我需要保证这种交易的原子性,保存所有的书或者不保存任何一本书。提前致谢:)
saveAll()
方法在SimpleJpaRepository
类中实现。
@Transactional
@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
}
它有
@Transactional
注释。您的服务方法没有 @Transactional
注释。所以这意味着回滚仍然会发生,即使你捕获了一个异常。在这种情况下,您不需要重新抛出异常。
否则,如果您将
@Transactional
放入您的 saveAllBooks()
方法中,回滚将不会发生。 saveAllBooks()
的注解取消saveAll()
的注解的原因。
@Transactional
public void saveAllBooks(List<Book> books) {
try {
bookRepository.saveAll(books);
} catch (DataAccessException e) {
// notify external service about failure
// log exception
}
}
首先需要澄清的是什么。当您使用 Spring Data JPA 时,注释 @Repository 是无关紧要的,将被忽略。 Spring 将改为使用 EnableJpaRepositories 并为每个扩展 JPARepository 的接口配置 SimpleJPARepository 的代理。你的 BookRepository 做了什么。因此,该存储库的所有方法都是事务性的。
这些方法中抛出的所有异常都将由 Spring 翻译并:
这将在 try/catch 逻辑之前独立发生。