Spring Framework поддерживает интеграцию с Java Persistence API (JPA) и поддерживает нативный Hibernate для управления ресурсами, реализации объектов доступа к данным (DAO) и стратегии транзакций. Например, для Hibernate имеются первоклассные средства поддержки с несколькими удобными IoC-функциями, которые решают многие типичные проблемы интеграции Hibernate. Можно сконфигурировать все поддерживаемые функции для инструментов OR (объектно-реляционного) отображения с помощью внедрения зависимостей. Они могут участвовать в управлении ресурсами и транзакциями Spring, а также они соответствуют типизированным иерархиям транзакций и исключений DAO в Spring. Рекомендуемый стиль интеграции – кодировать DAO вместо простых API-интерфейсов Hibernate или JPA.
Spring привносит значительные средства, расширяющие функционал, в выбранный вами уровень ORM при создании приложений доступа к данным. Можно использовать столько средств поддержки интеграции, сколько пожелаете, и затем сравните эти усилия по интеграции со стоимостью и риском создания аналогичной инфраструктуры собственными силами. Можно использовать большую часть средств поддержки ORM так же, как и библиотеки, независимо от технологии, потому что все разработано в виде набора многократно используемых JavaBeans. ORM в IoC-контейнере Spring облегчает конфигурирование и развертывание. Таким образом, в большинстве примеров в данном разделе показана конфигурация внутри контейнера Spring.
Преимуществами использования Spring Framework для создания ORM DAO-объектов являются:
-
Упрощенное тестирование. IoC-подход Spring позволяет с легкостью менять местами реализации и конфигурации экземпляров
SessionFactory
из Hibernate, экземпляровDataSource
из JDBC, диспетчеров транзакций и реализаций отображенных объектов (при необходимости). Это, в свою очередь, значительно облегчает тестирование каждой части кода, связанного с постоянным хранением, в отдельности. -
Общие исключения доступа к данным. Spring может обернуть исключения из вашего ORM-инструмента, преобразуя их из собственных (потенциально проверяемых) исключений в общую иерархию
DataAccessException
. Эта функция позволяет обрабатывать большинство исключений постоянного хранения, которые не подлежат восстановлению, только на соответствующих уровнях, без раздражающих стереотипных перехватов, генерации и объявления исключений. Но все еще можно отлавливать и обрабатывать исключения по мере необходимости. Помните, что исключения JDBC (включая диалекты, специфичные для БД) также преобразуются в ту же иерархию, что означает, что можно выполнять некоторые операции с JDBC в рамках модели согласованного программирования. -
Общее управление ресурсами. Контексты приложений Spring могут обрабатывать местоположение и конфигурацию экземпляров
SessionFactory
из Hibernate, экземпляровEntityManagerFactory
из JPA, экземпляровDataSource
из JDBC и других связанных ресурсов. Это упрощает управление и изменение этих значений. Spring предлагает эффективную, простую и безопасную работу с ресурсами постоянного хранения. Например, в зависимом коде, использующем Hibernate, обычно нужно использовать одну и ту жеSession
из Hibernate для обеспечения эффективности и надлежащей обработки транзакций. Spring позволяет легко создать и привязатьSession
к текущему потоку прозрачным образом, открывая текущуюSession
черезSessionFactory
из Hibernate. Таким образом, Spring решает многие хронические проблемы типичного пользования Hibernate для любого локального или транзакционного JTA-окружения. -
Интегрированное управление транзакциями. Можно обернуть ORM-код декларативным перехватчиком методов на основе аспектно-ориентированного программирования (АОП) либо с помощью аннотации
@Transactional
, либо явным образом сконфигурировав АОП-Advice для транзакций в XML-файле конфигурации. В обоих случаях семантика транзакций и обработка исключений (откат и т.д.) выполняются за вас. Как было описано в разделе " Управление ресурсами и транзакциями" , также можно менять различные диспетчеры транзакций, не затрагивая код, связанный с ORM. Например, можно переключаться между локальными транзакциями и JTA, при этом в обоих сценариях будут доступны одни и те же полноценные службы (например, декларативные транзакции). Кроме того, код, связанный с JDBC, может полностью транзакционно интегрироваться с кодом, который используется для ORM. Это полезно для такой организации доступа к данным, которая не подходит для ORM (например, пакетная обработка и потоковая передача BLOB), но при этом необходимо совместно использовать общие транзакции вместе с операциями ORM.
Общие подходы к интеграции ORM
В этом разделе рассматриваются рекомендации, применимые ко всем ORM-технологиям. Раздел, посвященный Hibernate, содержит более подробную информацию, а также демонстрирует эти возможности и конфигурации в конкретном контексте.
Основной целью интеграции ORM в Spring является четкая компоновка приложений (при любой технологии доступа к данным и транзакциях) и свободное связывание объектов приложения – больше никаких зависимостей бизнес-служб от стратегии доступа к данным или транзакций, никакого жестко закодированного поиска ресурсов, никаких труднозаменяемых объектов-одиночек, а также никаких кастомных реестров служб. Цель в том, чтобы организовать один простой и последовательный подход к обнаружению и связыванию объектов приложения, в максимально возможной мере обеспечивая возможность их повторного использования и свободу от зависимостей от контейнеров. Все отдельные функции доступа к данным можно использовать порознь, но также они прекрасно взаимодействуют с концепцией контекста приложения из Spring, предоставляя конфигурацию на основе XML и перекрестные ссылки на обычные экземпляры JavaBean, которые не обязательно должны быть совместимы со Spring. В типичном приложении Spring многие важные объекты являются JavaBeans: шаблоны доступа к данным, объекты доступа к данным, диспетчеры транзакций, бизнес-службы, использующие объекты доступа к данным и диспетчеры транзакций, распознаватели веб-представлений, веб-контроллеры, использующие бизнес-службы, и так далее.
Управление ресурсами и транзакциями
В типичных бизнес-приложениях существует нагромождение повторяющегося кода для управления ресурсами. Многие проекты пытаются придумать собственные решения, иногда жертвуя надлежащим устранением сбоев в угоду удобства программирования. Spring выступает за простые решения для надлежащей обработки ресурсов, а именно IoC через шаблонизацию в случае JDBC и применение перехватчиков АОП для ORM-технологий.
Инфраструктура обеспечивает надлежащую обработку ресурсов и соответствующее преобразование специфических исключений API-интерфейсов в непроверяемую иерархию исключений инфраструктуры. Spring вводит иерархию исключений DAO, применимую к любой стратегии доступа к данным. В случае прямого JDBC класс JdbcTemplate
, упомянутый в предыдущем разделе, обеспечивает обработку соединений и правильное преобразование SQLException
в иерархию DataAccessException
, включая преобразование специфических для базы данных кодов ошибок SQL в осмысленные классы исключений. В случае ORM-технологий см. следующий раздел о том, как воспользоваться теми же преимуществами преобразования исключений.
Если дело доходит до управления транзакциями, класс JdbcTemplate
подключается к средствам поддержки транзакций Spring и поддерживает транзакции JTA и JDBC через соответствующие диспетчеры транзакций Spring. Что касается поддерживаемых ORM-технологий, Spring предлагает поддержку Hibernate и JPA через менеджеры транзакций Hibernate и JPA, а также поддержку JTA. Подробнее о поддержке транзакций см. в главе "Управление транзакциями".
Преобразование исключений
Если Hibernate или JPA используются в DAO, то нужно решить, каким образом обрабатывать нативные классы исключений технологии поддержки постоянного хранения. DAO генерирует подкласс HibernateException
или PersistenceException
в зависимости от технологии. Все эти исключения являются исключениями времени выполнения и не должны быть объявлены или перехвачены. Возможно, также придется столкнуться с IllegalArgumentException
и IllegalStateException
. Это означает, что вызывающие программы могут работать только с теми исключениями, которые считаются критическими, если нужно избежать зависимости от собственной структуры исключений технологии поддержки постоянного хранения. Выяснить конкретные причины (таких как сбой оптимистической блокировки) невозможно без привязки вызывающей программы к стратегии реализации. Такой компромисс может быть приемлем для приложений, которые в значительной степени основаны на ORM или не нуждаются в особом обращении с исключениями (или и то, и другое). Однако Spring позволяет прозрачно применять преобразование исключений через аннотацию @Repository
. В следующих примерах (один для конфигурации на Java и один для конфигурации на XML) показано, как это сделать:
@Repository
public class ProductDaoImpl implements ProductDao {
// тело класса здесь...
}
@Repository
class ProductDaoImpl : ProductDao {
// тело класса здесь...
}
<beans>
<!-- Исключение постпроцессора преобразования бинов... -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>
Постпроцессор автоматически ищет все преобразователи исключений (реализации интерфейса PersistenceExceptionTranslator
) и снабажет Advice-ом все бины, помеченные аннотацией @Repository
, чтобы обнаруженные преобразователи смогли перехватить и применить соответствующее преобразование к сгенерированным исключениям.
В целом, можно реализовать DAO на основе API-интерфейса и аннотаций обычной технологии поддержки постоянного хранения, пользуясь при этом преимуществами транзакций, управляемых Spring, внедрения зависимостей и прозрачного преобразования исключений (при желании) в кастомные иерархии исключений Spring.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ