Spring Транзакция репозитория JPA

1 быстрый вопрос о транзакциях репозиториев JPA Spring. У меня есть служба, которая не помечена как транзакционная, и вызывает метод репозитория JPA Spring

userRegistrationRepository.deleteByEmail(email);

И он определяется как

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

    UserRegistration findByEmail(String email);

    void deleteByEmail(String email);

}

Проблема заключается в том, что она не работает с "No EntityManager с реальной транзакцией, доступной для текущего потока", не может надежно обработать "удалить" вызов, а вложенное исключение - исключение javax.persistence.TransactionRequiredException.

Хорошо, я могу решить это, отметив метод или deleteByEmail (..) как транзакционный, но я просто не могу понять, почему он сбой теперь. В документации Spring явно указано, что "методы CRUD на экземплярах репозитория по умолчанию являются транзакционными". (http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions), но, по-видимому, это не так... Итак, это утверждение относится только к членам CrudRepository?

ps: для Spring данных JPA 1.9.4

Ответ 1

Ты прав. Только методы CRUD (CrudRepository) по умолчанию помечены как транзакционные. Если вы используете пользовательские методы запроса, вы должны явно пометить его аннотацией @Transactional.

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

    UserRegistration findByEmail(String email);

    @Transactional
    void deleteByEmail(String email);

}

Вы также должны знать о последствиях маркировки методов интерфейса репозитория вместо методов обслуживания. Если вы используете конфигурацию распространения транзакций по умолчанию (Propagation.REQUIRED), то:

Конфигурация транзакции в репозиториях будет игнорироваться затем, поскольку конфигурация внешней транзакции определяет фактическую используется.

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

Если вам нужна дополнительная информация о том, как она реализована, взгляните на реализацию по умолчанию CrudRepository/JpaRepository - SimpleJpaRepository (которую вы, вероятно, используете):

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

  Интересные строки здесь:

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

и некоторые из транзакционных методов здесь:

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