简体   繁体   中英

Spring Boot With @Transactional annotated method, calls other transactional methods and throws an Exception

I am trying to process a record within a @Transactional annotated method. There are some dependencies from other methods that must be taken care before processing some other secondary (but necessary) business logic. The main record seems to be saved with no problem inside the transaction, but when I try to clean some data by using another service, it throws a JpaEntityNotFoundException .

I used Propagation.REQUIRES_NEW in the method that causes the issue, but with no success. Does anyone have an idea about what I am missing or doing wrong? I must not commit the main record before doing the rest of the transactional operations.

The exception that I am getting is: 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............... 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...............

Here is an example that shows somehow my issue:

ServiceA class

@Service
public class ServiceA {


    public void nonTransactionalMethodA(Book book) {

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

        updateAuthor(book);

        nonTransactionalMethodB();
    }

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

}

ServiceB Class

  @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);            
        }
    }   

Any thought on this will be greatly appreciated.

Make sure that the method annotated with @Transactional is declared as public and called by a different class.

A transactional method must be public so that Spring can override it and it must be called from outside the defining class so that the invocation can go through a proxy.

It's one of the common pitfalls when using @Transactional, for more information seehttps://codete.com/blog/5-common-spring-transactional-pitfalls/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM