带有@Transactional注释方法的Spring Boot调用其他事务方法并引发异常

时间:2019-12-23 18:33:32

标签: java spring spring-boot transactions spring-data

我正在尝试使用带有@Transactional注释方法的记录。在处理一些其他辅助(但必要)业务逻辑之前,必须注意其他方法的某些依赖性。主记录似乎在事务内部没有问题地被保存,但是当我尝试使用另一服务来清理一些数据时,它会抛出一个JpaEntityNotFoundException

我在导致问题的方法中使用了Propagation.REQUIRES_NEW,但没有成功。有谁知道我的缺失或做错了什么?在执行其余的事务操作之前,我一定不能提交主记录。

我得到的例外是:org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com.myproject.repository.entity.Book with id 5851445; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.myproject.repository.entity.Book with id 5851445...............

这是一个以某种方式显示我的问题的示例:

ServiceA类

@Service
public class ServiceA {


    public void nonTransactionalMethodA(Book book) {

        //..... Any independent logic from ServiceB

        updateAuthor(book);

        nonTransactionalMethodB();
    }

    public void nonTransactionalMethodB() {
        //post process logic ......
    }

}

ServiceB类

  @Service
  public class ServiceB {

        @Autowired
        private BookRepository bookRepository;

        @Autowired
        private OfferRepository offerRepository;

        @Transactional
        private void updateAuthor(Author author) {
            Book book = new Book(1);
            book.setAuthor(author);
            bookRepository.save(book);
            removeUnavailableOffers(book);        
        }

        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void removeUnavailableOffers (Book book) {
            /*throwing org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com.myproject.repository.entity.Book with id 5851445; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.myproject.repository.entity.Book with id 5851445............*/
            offerRepository.deleteByBookIdIsNullAndBookAuthorIdNot(book.authorId);            
        }
    }   

任何对此的想法将不胜感激。

1 个答案:

答案 0 :(得分:1)

确保用footer.php注释的方法被声明为@Transactional并由其他类调用。

事务方法必须是公共的,以便Spring可以覆盖它,并且必须从定义类的外部调用它,以便调用可以通过代理进行。

这是使用@Transactional时的常见陷阱之一,有关更多信息,请参见https://codete.com/blog/5-common-spring-transactional-pitfalls/