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, включаючи підтримку альтернативних технологій баз даних, таких як MongoDB, варто звернути увагу на набір проектів Spring Data. Якщо ви є користувачем JPA, посібник "Початок роботи з доступом до даних за допомогою JPA" з сайту https://spring.io буде чудовим введенням.

Загальні підходи до інтеграції ORM

У цьому розділі наведено рекомендації щодо всіх ORM-технологій. Розділ, присвячений Hibernate, містить більш детальну інформацію, а також демонструє ці можливості та конфігурації в конкретному контексті.

Основною метою інтеграції ORM у Spring є чітке компонування додатків (за будь-якої технології доступу до даних та транзакцій) та вільне зв'язування об'єктів додатку – більше ніяких залежностей бізнес-служб від стратегії доступу до даних чи транзакцій, жодного жорстко закодованого пошуку ресурсів, жодних важкозамінних об'єктів-одинаків, і навіть ніяких кастомних реєстрів служб. Мета в тому, щоб організувати один простий і послідовний підхід до виявлення та зв'язування об'єктів програми, максимально можливою мірою забезпечуючи можливість їх повторного використання та свободу від залежностей від контейнерів. Всі окремі функції доступу до даних можна використовувати порізно, але вони чудово взаємодіють з концепцією контексту програми з Spring, надаючи конфігурацію на основі XML і перехресні посилання на звичайні екземпляри JavaBean, які не обов'язково повинні бути сумісні зі Spring. У типовому додатку Spring багато важливих об'єктів є JavaBeans: шаблони доступу до даних, об'єкти доступу до даних, диспетчери транзакцій, бізнес-служби, що використовують об'єкти доступу до даних і диспетчери транзакцій, розпізнавачі веб-уявлень, веб-контролери, що використовують бізнес-служби, і так далі.

Керування ресурсами та транзакціями

У типових бізнес-додатках існує нагромадження повторюваного коду для управління ресурсами. Багато проектів намагаються придумати власні рішення, іноді жертвуючи належним усуненням збоїв для зручності програмування. Spring виступає за прості рішення для належної обробки ресурсів, а саме IoC через шаблонизацію у випадку JDBC та застосування перехоплювачів АОП для ORM-технологій. винятків інфраструктури. 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) показано, як це зробити:

Java
@Repository public class ProductDaoImpl implements ProductDao { / / тіло класу тут... }
Kotlin
@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.