Як створювати різні диспетчери транзакцій і як вони пов'язані з відповідними ресурсами, які мають бути синхронізовані з транзакціями (наприклад, DataSourceTransactionManager з DataSource з JDBC, HibernateTransactionManager з SessionFactory з Hibernate і так далі), має тепер бути зрозумілим. У цьому розділі описано, як код програми (прямо чи опосередковано, за допомогою API-інтерфейсу збереження, такого як JDBC, Hibernate або JPA) забезпечує створення, повторне використання та очищення цих ресурсів належним чином. У розділі також розглянуто те, як синхронізацію транзакцій (опціонально) можна запустити через відповідний TransactionManager.

Підхід із використанням високорівневої синхронізації

Підходом, якому надається перевага, є використання високорівневих інтеграційних API-інтерфейсів збереження на основі шаблонів зі Spring або використання власних ORM API-інтерфейсів з транзакційно-орієнтованими бінами-фабриками або проксі для управління нативними фабриками ресурсів. Ці транзакційно-орієнтовані рішення на внутрішньому рівні обробляють створення та повторне використання ресурсів, очищення, опціональну синхронізацію ресурсів із транзакціями та перетворенням винятків. Таким чином, користувацькому коду доступу до даних не потрібно вирішувати ці завдання, а замість цього його можна переорієнтувати виключно на нестереотипну логіку збереження даних. Зазвичай ти використовуєш вбудований ORM API інтерфейс або застосовуєш підхід, заснований на шаблонах, для отримання доступу за стандартом JDBC за допомогою JdbcTemplate. Ці програмні рішення докладно описані у наступних розділах цієї довідкової документації.

Підхід із використанням низькорівневої синхронізації

Такі класи, як DataSourceUtils (для JDBC), EntityManagerFactoryUtils (для JPA), SessionFactoryUtils (для Hibernate) тощо, існують на нижчому рівні. Якщо тобі потрібно, щоб код програми працював безпосередньо з типами ресурсів нативних API-інтерфейсів збереження, то використовуй ці класи для забезпечення отримання належних екземплярів, керованих Spring Framework, синхронізації транзакцій (опціонально) та правильного відображення винятків, що виникають у процесі, в узгодженому API-інтерфейсі.

Наприклад, у випадку з JDBC замість традиційного для JDBC підходу з викликом методу getConnection() для DataSource, можна використовувати клас org.springframework.jdbc. datasource.DataSourceUtils зі Spring, як показано нижче:

Connection conn = DataSourceUtils.getConnection(dataSource);

Якщо існуюча транзакція вже має синхронізоване (прив'язане) з нею з'єднання, повертається цей екземпляр. В іншому випадку виклик методу призводить до створення нового з'єднання, яке (опціонально) синхронізується з будь-якою існуючою транзакцією і стає доступним для подальшого повторного використання тієї ж транзакції. Як згадувалося раніше, будь-який виняток SQLException обертається у виняток CannotGetJdbcConnectionException зі Spring Framework, який є одним з винятків ієрархії неперевірених типів DataAccessException у Spring Framework. Такий підхід дає більше інформації, яку без проблем можна отримати з SQLException, та забезпечує переносимість між базами даних і навіть між різними технологіями постійного зберігання.

Цей підхід також працює без керування транзакціями зі Spring (синхронізація транзакцій необов'язкова), тому можна користуватися ним незалежно від того, чи ти використовуєш Spring для керування транзакціями чи ні.

Звісно, після використання засобів підтримки Spring для JDBC, JPA або Hibernate, зазвичай краще не використовувати DataSourceUtils або інші допоміжні класи, оскільки тобі буде набагато приємніше працювати через абстракцію Spring, ніж безпосередньо з відповідними API-інтерфейсами. Наприклад, якщо ти використовуєш Spring JdbcTemplate або пакет jdbc.object для спрощення використання JDBC, коректний пошук з'єднання відбувається "за лаштунками", і тобі не потрібно писати спеціальний код.

TransactionAwareDataSourceProxy

На найнижчому рівні існує клас TransactionAwareDataSourceProxy. Це проксі для цільового DataSource, який обертає цільовий DataSource, щоб підвищити рівень сумісності транзакцій, керованих Spring. У цьому сенсі він схожий на транзакційний DataSource з JNDI, який надається сервером Java EE.

Тобі майже ніколи не знадобиться або не захочеться використовувати цей клас, за винятком випадків, коли необхідно викликати існуючий код та передати йому стандартну реалізацію інтерфейсу DataSource з JDBC. У цьому випадку можливо, що цей код можна використовувати, але він бере участь у транзакціях, керованих Spring. Можна написати новий власний код, використовуючи абстракції вищого рівня, згадані раніше.