Всеобъемлющая поддержка транзакций является одной из наиболее веских причин использовать Spring Framework. Spring Framework предоставляет согласованную абстракцию для управления транзакциями, которая обеспечивает следующие преимущества:

  • Согласованная модель программирования для различных API-интерфейсов транзакций, таких как Java Transaction API (JTA), JDBC, Hibernate и Java Persistence API (JPA).

  • Поддержка декларативного управления транзакциями.

  • Упрощенный API-интерфейс для программного управления транзакциями вместо сложных API-интерфейсов транзакций, таких как JTA.

  • Превосходная интеграция с абстракциями доступа к данным из Spring.

Преимущества модели поддержки транзакций Spring Framework

Традиционно у разработчиков Java EE было два варианта управления транзакциями: через глобальные или локальные транзакции, причем оба из этих двух вариантов имеют серьёзные ограничения. Глобальное и локальное управление транзакциями рассмотрены в следующих двух разделах, после чего следует описание того, каким образом средства поддержки управления транзакциями в Spring Framework устраняют ограничения глобальной и локальной моделей транзакций.

Глобальные транзакции

Глобальные транзакции позволяют работать с несколькими транзакционными ресурсами, обычно реляционными базами данных и очередями сообщений. Сервер приложений управляет глобальными транзакциями через JTA, который является громоздким API-интерфейсом (отчасти из-за его модели исключений). Кроме того, UserTransaction из JTA обычно необходимо получать из JNDI, а это означает, что также приходится использовать JNDI, чтобы использовать JTA. Использование глобальных транзакций ограничивает любое потенциальное повторное использование кода приложения, поскольку JTA обычно доступен только в окружении сервера приложений.

Ранее предпочтительным способом использования глобальных транзакций был метод с использованием транзакций EJB, управляемых контейнером (Container Managed Transaction/CMT). CMT является формой декларативного управления транзакциями (в отличие от программного управления транзакциями). CMT из EJB устраняет необходимость в связанном с транзакциями поиске через JNDI, хотя использование самого EJB требует использования JNDI. Это позволяет избавиться по большей части, хоть и не полностью, от необходимости писать Java-код для управления транзакциями. Существенным недостатком является то, что CMT привязан к JTA и окружению сервера приложений. Кроме того, он доступен только в том случае, если вы решите реализовать бизнес-логику в классах EJB (или, по крайней мере, в пределах транзакционного фасада EJB). Недостатки EJB в целом столь значительны, что его использование перестает быть привлекательным, особенно в сравнении с адекватными альтернативами для декларативного управления транзакциями.

Локальные транзакции

Локальные транзакции зависят от ресурса, как, например, в случае с транзакцией, связанной с подключением JDBC. Локальные транзакции могут быть проще в использовании, но имеют существенный недостаток: Они не могут работать с несколькими транзакционными ресурсами. Например, код, который управляет транзакциями с помощью подключения JDBC, не может выполняться в глобальной транзакции JTA. Поскольку сервер приложений не участвует в управлении транзакциями, он не может обеспечить корректность работы с несколькими ресурсами. (Стоит отметить, что большинство приложений используют один ресурс транзакции.) Другим недостатком является то, что локальные транзакции действуют агрессивно в отношении модели программирования.

Модель согласованного программирования в Spring Framework

Spring устраняет недостатки глобальных и локальных транзакций. Это позволяет разработчикам приложений использовать модель согласованного программирования в любом окружении. Вы пишете свой код один раз, а он в свою очередь может пользоваться разными стратегиями управления транзакциями в разных окружениях. Spring Framework обеспечивает как декларативное, так и программное управление транзакциями. Большинство пользователей предпочитают декларативное управление транзакциями, которое мы и рекомендуем в большинстве случаев.

При программном управлении транзакциями разработчики имеют дело с абстракцией транзакций Spring Framework, которая может работать в любой базовой инфраструктуре транзакций. При использовании предпочтительной декларативной модели разработчики обычно пишут небольшой объем или вообще не пишут код, связанный с управлением транзакциями, и, следовательно, не зависят от API-интерфейса транзакций из Spring Framework или любого другого API-интерфейса транзакций.

Нужен ли сервер приложений для управления транзакциями?

Поддержка управления транзакциями Spring Framework изменяет традиционные правила в отношении обязательного наличия сервера приложений для Java-приложения.

В частности, если речь идет исключительно о декларативных транзакциях через классы EJB, сервер приложений не требуется. Фактически, даже если ваш сервер приложений обладает полнофункциональными средствами JTA, вы все равно можете задуматься о том, что декларативные транзакции Spring Framework обеспечивают больший функционал и более продуктивную модель программирования, чем CMT из EJB.

Как правило, возможности JTA сервера приложений требуется только в том случае, если приложению необходимо обрабатывать транзакции по нескольким ресурсам, что не является обязательным требованием для многих приложений. Многие приложения высшего класса вместо этого используют единую хорошо масштабируемую базу данных (например, Oracle RAC). Автономные диспетчеры транзакций (такие как Atomikos Transactions и JOTM) являются еще одним вариантом. Конечно, могут потребоваться другие средства сервера приложений, такие как Служба сообщений Java (Java Message Service/JMS) и Архитектура коннекторов Java EE ( Java EE Connector Architecture/JCA).

Платформа Spring Framework позволяет выбрать время масштабирования приложения до полностью загруженного сервера приложений. Прошли те времена, когда единственной альтернативой использованию CMT из EJB или JTA было написание кода с локальными транзакциями (например, в соединениях JDBC) и приходилось сталкиваться с необходимостью значительного переписывания кода, если нужно, чтобы этот код выполнялся в границах глобальных транзакций, управляемых контейнером. В Spring Framework необходимо изменить только некоторые определения бинов в файле конфигурации (а не код).