Reputation: 199
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...............
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.
Upvotes: 1
Views: 4068
Reputation: 5123
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 see https://codete.com/blog/5-common-spring-transactional-pitfalls/
Upvotes: 2