Сделки с Spring и JPA

Сделки с Spring и JPA

1. обзор

В этом руководстве будет обсуждатьсяthe right way to configure Spring Transactions, как использовать аннотацию@Transactional и распространенные ошибки.

Для более глубокого обсуждения основной конфигурации персистентности ознакомьтесь с файломSpring with JPA tutorial.

По сути, есть два разных способа настройки транзакций - аннотации и AOP - каждый со своими преимуществами. Мы собираемся обсудить здесь более распространенную конфигурацию аннотации.

Дальнейшее чтение:

Настройка отдельного источника данных Spring для тестов

Краткое практическое руководство по настройке отдельного источника данных для тестирования в приложении Spring.

Read more

Краткое руководство по загрузке исходных данных с помощью Spring Boot

Быстрый и практический пример использования файлов data.sql и schema.sql в Spring Boot.

Read more

Показать Hibernate / JPA-операторы SQL из Spring Boot

Узнайте, как можно настроить ведение журнала сгенерированных операторов SQL в приложении Spring Boot.

Read more

2. Настроить транзакции без XML

Spring 3.1 представляетthe @EnableTransactionManagement annotation, который мы можем использовать в классе@Configuration и включить поддержку транзакций:

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{

   @Bean
   public LocalContainerEntityManagerFactoryBean
     entityManagerFactoryBean(){
      //...
   }

   @Bean
   public PlatformTransactionManager transactionManager(){
      JpaTransactionManager transactionManager
        = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(
        entityManagerFactoryBean().getObject() );
      return transactionManager;
   }
}

Однако, если мы используем проект Spring Boot и имеем зависимости spring-data- * или spring-tx от пути к классам, то управление транзакциями будет включено по умолчанию.

3. Настроить транзакции с помощью XML

До версии 3.1 или если Java не подходит, вот конфигурация XML с использованиемannotation-driven и поддержки пространства имен:


   

4. Аннотация@Transactional

С настроенными транзакциями мы можем теперь аннотировать bean-компонент с помощью@Transactional либо на уровне класса, либо на уровне метода:

@Service
@Transactional
public class FooService {
    //...
}

Аннотация также поддерживаетfurther configuration:

  • Propagation Type транзакции

  • Isolation Level транзакции

  • Timeout для операции, заключенной в транзакцию

  • areadOnly flag - подсказка для поставщика сохраняемости, что транзакция должна быть доступна только для чтения

  • правилаRollback для транзакции

Обратите внимание, что по умолчанию откат происходит только во время выполнения, только непроверенные исключения. The checked exception does not trigger a rollback транзакции. Конечно, мы можем настроить это поведение с помощью параметров аннотацииrollbackFor иnoRollbackFor.

5. Потенциальные ловушки

5.1. Транзакции и прокси

На высоком уровнеSpring creates proxies for all the classes annotated with @Transactional - либо на классе, либо на любом из методов. Прокси-сервер позволяет инфраструктуре внедрять транзакционную логику до и после метода выполнения - главным образом для запуска и фиксации транзакции.

Важно помнить, что если транзакционный компонент реализует интерфейс, по умолчанию прокси-сервером будет Java Dynamic Proxy. Это означает, что будут перехватываться только внешние вызовы методов, которые поступают через прокси. Any self-invocation calls will not start any transaction,, даже если метод имеет аннотацию@Transactional.

Еще одно предостережение при использовании прокси заключается в том, что методыonly public methods should be annotated with @Transactional. любой другой видимости просто игнорируют аннотацию, поскольку они не передаются через прокси.

This article discusses further proxying pitfalls здесь очень подробно.

5.2. Изменение уровня изоляции

Мы также можем изменить уровень изоляции транзакции:

@Transactional(isolation = Isolation.SERIALIZABLE)

Обратите внимание, что на самом деле это былоintroduced в Spring 4.1; если мы запустим приведенный выше пример до Spring 4.1, это приведет к:

org.springframework.transaction.InvalidIsolationLevelException: стандартный JPA не поддерживает настраиваемые уровни изоляции - используйте специальныйJpaDialect для вашей реализации JPA

5.3. Транзакции только для чтения

ФлагreadOnly обычно вызывает путаницу, особенно при работе с JPA; из Javadoc:

Это просто подсказка для самой подсистемы транзакций; not necessarily приведет к сбою попыток доступа для записи. Диспетчер транзакций, который не может интерпретировать подсказку только для чтения, будет вызывать исключениеnot при запросе транзакции только для чтения.

Дело в том, чтоwe can’t be sure that an insert or update will not occur when the readOnly flag is set. Это поведение зависит от поставщика, тогда как JPA не зависит от поставщика.

Также важно понимать, чтоthe readOnly flag is only relevant inside a transaction. Если операция происходит вне транзакционного контекста, флаг просто игнорируется. Простой пример этого - вызов метода с аннотацией:

@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )

из нетранзакционного контекста - транзакция не будет создана, а флагreadOnly будет проигнорирован.

5.4. Ведение журнала транзакций

Полезным методом для понимания проблем, связанных с транзакциями, является точная настройка ведения журналов в транзакционных пакетах. Соответствующий пакет в Spring - «org.springframework.transaction”, which should be configured with a logging level of TRACE.

6. Заключение

Мы рассмотрели базовую конфигурацию семантики транзакций с использованием как Java, так и XML, способы использования@Transactional и лучшие практики транзакционной стратегии.

Как всегда, доступен код, представленный в этой статьеover on Github.