web-dev-qa-db-fra.com

Transactionnalité du référentiel Spring JPA

1 petite question sur la transactionnalité des référentiels Spring JPA. J'ai un service qui n'est pas marqué comme transactionnel et appelle la méthode de référentiel Spring JPA

userRegistrationRepository.deleteByEmail(email);

Et il est défini comme

@Repository
public interface UserRegistrationRepository extends JpaRepository<UserRegistration, Long> {

    UserRegistration findByEmail(String email);

    void deleteByEmail(String email);

}

Le problème est qu'il échoue avec " Aucun EntityManager avec la transaction réelle disponible pour le thread actuel - ne peut pas traiter de manière fiable l'appel 'remove'; l'exception imbriquée est l'exception javax.persistence.TransactionRequiredException".

Ok, je peux le résoudre en marquant le service ou deleteByEmail (..) comme transactionnel, mais je viens ne peut pas comprendre pourquoi il se bloque maintenant. La documentation de Spring indique explicitement que " Les méthodes CRUD sur les instances de référentiel sont transactionnelles par défaut." ( http://docs.spring.io/spring-data/jpa/docs/current/reference/html/# transactions ), mais apparemment celui-ci ne l'est pas ... Donc, cette déclaration concerne-t-elle uniquement les membres de CrudRepository?

ps: c'est pour Spring Data JPA 1.9.4

18
FlasH from Ru

Tu as raison. Seules les méthodes CRUD (méthodes CrudRepository) sont par défaut marquées comme transactionnelles. Si vous utilisez des méthodes de requête personnalisées, vous devez explicitement le marquer avec @Transactional annotation.

@Repository
public interface UserRegistrationRepository extends JpaRepository<UserRegistration, Long> {

    UserRegistration findByEmail(String email);

    @Transactional
    void deleteByEmail(String email);

}

Vous devez également être conscient des conséquences du marquage des méthodes d'interface de référentiel au lieu des méthodes de service. Si vous utilisez la configuration de propagation des transactions par défaut (Propagation.REQUIRED) puis:

La configuration des transactions au niveau des référentiels sera alors négligée car la configuration des transactions externes détermine celle réellement utilisée.

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions

Si vous souhaitez plus d'informations sur la façon dont il est implémenté, jetez un œil à l'implémentation par défaut CrudRepository/JpaRepository - SimpleJpaRepository (que vous utilisez probablement):

https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/Java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.Java

Les lignes intéressantes sont ici:

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

et certaines des méthodes transactionnelles ici:

@Transactional
public void deleteById(ID id) {
@Transactional
public <S extends T> S save(S entity) {
27
Maciej Marczuk