Підтримка об'єкта доступу до даних (Data Access Object/DAO) у Spring спрямована на спрощення роботи з технологіями доступу до даних (таких як JDBC, Hibernate або JPA). Це дозволяє легко перемикатися між вищезазначеними технологіями підтримки постійного зберігання, а також не перейматися перехопленням винятків, характерних для кожної технології.

Узгоджена ієрархія винятків

Spring забезпечує зручний перехід від специфічних для технології винятків, таких як SQLException, до власної ієрархії класів винятків, у якій кореневим винятком є DataAccessException. Ці винятки огортають вихідний виняток, тому відсутній ризик того, що ти можеш втратити інформацію про те, що могло піти не так.

На додаток до винятків JDBC, Spring також може огорнути специфічні винятки JPA та Hibernate, перетворюючи їх на набір організованих винятків часу виконання. Це дозволяє обробляти більшість невідновлюваних винятків постійного зберігання лише на відповідних рівнях, не вдаючись до стереотипних блоків "catch-and-throw" та оголошень винятків у ваших DAO. (Однак ти все одно можеш відловлювати та обробляти винятки скрізь, де це необхідно). Як згадувалося вище, винятки JDBC (включно з діалектами, специфічними для баз даних) також перетворюються на ту саму ієрархію, що означає, що ти можеш виконувати деякі операції з JDBC в межах моделі узгодженого програмування.

Попереднє пояснення справедливе і щодо різних класів шаблонів у засобах підтримки Spring для різних ORM-фреймворків. Якщо ти використовуєш класи на основі перехоплювачів, програма повинна сама займатися обробкою HibernateExceptions та PersistenceExceptions, переважно делегуючи її методам convertHibernateAccessException(..) або convertJpaAccessException(..) утиліти SessionFactoryUtils відповідно. Ці методи перетворюють винятки на такі, що сумісні з винятками в ієрархії винятків org.springframework.dao. Оскільки PersistenceExceptions неперевірені, вони також можуть бути згенеровані (щоправда, жертвуючи типізованою абстракцією DAO у плані винятків).

На наступному зображенні показано ієрархію винятків, яку пропонує Spring. (Зверни увагу, що ієрархія класів, подана на малюнку, показує лише частину всієї ієрархії DataAccessException).

Анотації, що використовуються для налаштування класів DAO або репозиторію

Найкращий спосіб забезпечити те, щоб ваші об'єкти доступу до даних (DAO) або репозиторії гарантовано перетворювали (транслювали) винятки, — використовувати анотацію @Repository. Ця анотація також дозволяє засобам підтримки сканування компонентів знаходити та налаштовувати DAO та репозиторії без необхідності надавати для них XML-записи конфігурації. У цьому прикладі показано, як використовувати анотацію @Repository:

Java
@Repository 
public class SomeMovieFinder implements MovieFinder {
    // ...
}
  1. Анотація @Repository.
Kotlin
@Repository 
class SomeMovieFinder : MovieFinder {
    // ...
}
  1. Анотація @Repository.

Будь-якій реалізації DAO або репозиторію потрібен доступ до ресурсу постійного зберігання, залежно від технології постійного зберігання, що використовується. Наприклад, репозиторію на основі JDBC необхідний доступ до DataSource з JDBC, а сховищу на основі JPA — доступ до EntityManager. Найпростіший спосіб досягти цього — впровадити залежність ресурсу за допомогою однієї з анотацій @Autowired, @Inject, @Resource або @PersistenceContext. Наступний приклад є робочим щодо репозиторію JPA:

Java
@Repository
public class JpaMovieFinder implements MovieFinder {
    @PersistenceContext
    private EntityManager entityManager;
    // ...
}
Kotlin
@Repository
class JpaMovieFinder : MovieFinder {
    @PersistenceContext
    private lateinit var entityManager: EntityManager
    // ...
}

Якщо використовуються класичні API-інтерфейси Hibernate, можна впровадити SessionFactory, як показано в наступному прикладі:

Java
@Repository
public class HibernateMovieFinder implements MovieFinder {
    private SessionFactory sessionFactory;
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    // ...
}
Kotlin
@Repository
class HibernateMovieFinder(private val sessionFactory: SessionFactory) : MovieFinder {
    // ...
}

Останній приклад, який ми продемонструємо, стосується типового засобу підтримки JDBC. DataSource можна впровадити в метод ініціалізації або конструктор, де ти створиш JdbcTemplate та інші класи підтримки доступу до даних (такі як SimpleJdbcCall тощо), використовуючи цей DataSource. У наступному прикладі виконується автоматичне виявлення та зв'язування DataSource:

Java
@Repository
public class JdbcMovieFinder implements MovieFinder {
    private JdbcTemplate jdbcTemplate;
    @Autowired
    public void init(DataSource dataSource) {
        this.jdbcTemplate = новий JdbcTemplate(dataSource);
    }
    // ...
}
Kotlin
@Repository
class JdbcMovieFinder(dataSource: DataSource) : MovieFinder {
    private val jdbcTemplate = JdbcTemplate(dataSource)
    // ...
}
Докладну інформацію про те, як налаштувати контекст програми, щоб скористатися перевагами цих анотацій, див. у спеціальному описі кожної технології постійного зберігання.