1 quick question on Spring JPA repositories transactionality.
I have a service that is not marked as transactional and calls Spring JPA repository method
userRegistrationRepository.deleteByEmail(email);
And it is defined as
@Repository
public interface UserRegistrationRepository extends JpaRepository<UserRegistration, Long> {
UserRegistration findByEmail(String email);
void deleteByEmail(String email);
}
The problem is that it fails with "No EntityManager with actual transaction available for current thread – cannot reliably process 'remove' call; nested exception is javax.persistence.TransactionRequiredException" exception.
Ok, I can solve it by marking the service or deleteByEmail(..) method as transactional, but I just can't understand why it crashes now. Spring documentation explicitly states that "CRUD methods on repository instances are transactional by default." (http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions), but apparently this one is not… So Is this statement related to only members of CrudRepository
?
ps: that's for Spring Data JPA 1.9.4
Best Answer
You are right. Only CRUD methods (
CrudRepository
methods) are by default marked as transactional. If you are using custom query methods you should explicitly mark it with@Transactional
annotation.You should also be aware about consequences of marking repository interface methods instead of service methods. If you are using default transaction propagation configuration (
Propagation.REQUIRED
) then:http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
If you want more information about how it is implemented, take a look at default
CrudRepository
/JpaRepository
implementation -SimpleJpaRepository
(which you are probably using):https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java
The interesting lines are here:
and some of transactional methods here: