在 SpringBoot 中,如果我捕获到 DataAccessException,Transactional 注释是否仍然回滚事务

问题描述 投票:0回答:2

在使用 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
        }
    }

}

如果我这样做,回滚仍然会发生还是我需要重新抛出异常?我需要保证这种交易的原子性,保存所有的书或者不保存任何一本书。提前致谢:)

java spring-boot hibernate spring-data-jpa transactions
2个回答
1
投票

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
        }
    }

0
投票

首先需要澄清的是什么。当您使用 Spring Data JPA 时,注释 @Repository 是无关紧要的,将被忽略。 Spring 将改为使用 EnableJpaRepositories 并为每个扩展 JPARepository 的接口配置 SimpleJPARepository 的代理。你的 BookRepository 做了什么。因此,该存储库的所有方法都是事务性的。

这些方法中抛出的所有异常都将由 Spring 翻译并:

  • 任何未经检查的异常(如DataAccessException、IndexOutOfBoundsException)都会触发事务回滚
  • 任何已检查的异常(如 SQLException)都不会触发回滚

这将在 try/catch 逻辑之前独立发生。

© www.soinside.com 2019 - 2024. All rights reserved.