Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring JPA repository transactionality

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

like image 936
FlasH from Ru Avatar asked Oct 03 '16 08:10

FlasH from Ru


People also ask

Is @repository transactional?

The usage of the @Repository annotation or @Transactional . @Repository is not needed at all as the interface you declare will be backed by a proxy the Spring Data infrastructure creates and activates exception translation for anyway.

What is @transactional in Spring data JPA?

The @Transactional annotation is the metadata that specifies the semantics of the transactions on a method. We have two ways to rollback a transaction: declarative and programmatic. In the declarative approach, we annotate the methods with the @Transactional annotation.

How do I commit to a JPA repository?

Commit a transaction by calling the commit() method on the Connection interface. This tells your database to perform all required consistency checks and persist the changes permanently. Rollback all operations performed during the transaction by calling the rollback() method on the Connection interface.

Are JPA repository method transactional?

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.


1 Answers

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.

@Repository public interface UserRegistrationRepository extends JpaRepository<UserRegistration, Long> {      UserRegistration findByEmail(String email);      @Transactional     void deleteByEmail(String email);  } 

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:

The transaction configuration at the repositories will be neglected then as the outer transaction configuration determines the actual one used.

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:

@Transactional(readOnly = true) public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> { 

and some of transactional methods here:

@Transactional public void deleteById(ID id) { 
@Transactional public <S extends T> S save(S entity) { 
like image 108
Maciej Marczuk Avatar answered Oct 13 '22 18:10

Maciej Marczuk