【问题标题】:Spring Boot With @Transactional annotated method, calls other transactional methods and throws an ExceptionSpring Boot 带有@Transactional 注解的方法,调用其他事务方法并抛出异常
【发布时间】:2019-12-23 18:33:32
【问题描述】:

我正在尝试在 @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);            
        }
    }   

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

【问题讨论】:

  • 您想通过Propagation.REQUIRES_NEW 实现什么目标?它用于部分回滚,并非所有数据库都支持它。如果您有多个事务,则应使用 @Transactional 注释您的“其他”服务,并从另一个调用这两个服务的 @Transactional 方法调用,如果它想查看事务中所做的更改。附言@Modus 对私有方法的看法是正确的,@Transactional 永远不会对私有方法做任何事情
  • updateAuthor 在 ServiceB 中是私有的。你在哪里称呼它?它应该从另一个类中调用。
  • @ModusTollens 感谢您的通知。真正的实现具有公共访问的方法。
  • @AraKokheba 好的,但它仍然是从不同的类调用的,对吧?这是必要的,因此具有事务方法的类被代理。
  • @ModusTollens 很好的答案!!!我将事务更改为不同的类,然后它起作用了。谢谢。您应该发布作为答案,以便我可以投票嘻嘻

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


【解决方案1】:

确保使用@Transactional 注释的方法声明为public 并由不同的类调用。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    • 2015-05-15
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多