Статьи

Конфигурация транзакции с использованием JPA и Spring 3.1

1. Обзор

В этом руководстве будет обсуждаться правильный способ настройки Spring Транзакций , использование аннотации @Transactional и распространенных ошибок.

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

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

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{
 
   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
      ...
   }
 
   @Bean
   public PlatformTransactionManager transactionManager(){
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(
       entityManagerFactoryBean().getObject() );
      return transactionManager;
   }
}

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

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

1
2
3
4
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

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

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

1
2
3
4
5
@Service
@Transactional
public class FooService {
    ...
}

Аннотация также поддерживает дальнейшую настройку :

  • Тип распространения сделки
  • Уровень изоляции транзакции
  • Тайм-аут для операции, завернутой транзакцией
  • флаг readOnly — подсказка для поставщика постоянства, что транзакция должна быть только для чтения
  • подробная конфигурация отката

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

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

На высоком уровне Spring создает прокси для всех классов, помеченных @Transactional — либо для класса, либо для любого из методов. Прокси-сервер позволяет платформе внедрять транзакционную логику до и после вызова метода — главным образом для запуска и фиксации транзакции .

Важно помнить, что если транзакционный компонент реализует интерфейс, по умолчанию прокси будет динамическим прокси Java . Это означает, что будут перехватываться только внешние вызовы методов, которые поступают через прокси-сервер — любые вызовы самозапуска не будут запускать какие-либо транзакции — даже если метод аннотирован @Transactional .

Еще одна оговорка использования прокси-серверов заключается в том, что аннотацией @Transactional следует аннотировать только общедоступные методы — методы любой другой видимости будут просто молча игнорировать аннотацию, поскольку они не проксируются.

В этой статье подробно обсуждаются дальнейшие прокси-серверы .

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

Одна из основных ловушек при настройке Spring для работы с JPA заключается в том, что изменение изоляции семантики транзакции не будет работать — JPA не поддерживает настраиваемые уровни изоляции . Это ограничение JPA, а не Spring ; тем не менее изменение свойства изоляции @Transactional приведет к:

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

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

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

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

Дело в том, что нельзя гарантировать, что вставка или обновление не произойдут, если установлен флаг readOnly — его поведение зависит от поставщика, тогда как JPA не зависит от поставщика.

Также важно понимать, что флаг readOnly имеет значение только внутри транзакции ; если операция происходит вне контекста транзакции, флаг просто игнорируется. Простой пример этого — вызов метода с аннотацией:

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

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

5.4. Регистрация транзакций

Проблемы, связанные с транзакциями, также могут быть лучше поняты путем тонкой настройки регистрации в транзакционных пакетах; соответствующий пакет в Spring — « org.springframework.transaction», который должен быть настроен с уровнем ведения журнала TRACE.

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

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

Реализацию этого простого проекта можно найти в проекте github — это проект на основе Eclipse, поэтому его легко импортировать и запускать как есть.

Ссылка: Сделки с Spring 3 и JPA от нашего партнера JCG Юджина Параскива в блоге baeldung .