
Предлагаем ознакомиться с отрывком «Паттерн «Объект доступа к данным»»
«Объект доступа к данным» (Data Access Object, DAO) — чрезвычайно популярный паттерн проектирования для уровня сохранения в приложениях J2EE. Он отделяет уровень бизнес-логики от уровня сохранения. Паттерн DAO основан на объектно-ориентированных принципах инкапсуляции и абстракции. Контекст использования паттерна DAO — доступ к данным и их сохранение в зависимости от конкретной реализации и типа хранилища, например объектно-ориентированной базы данных, неструктурированных файлов, реляционных баз данных и т. д. На основе паттерна DAO можно создать интерфейс DAO и реализовать его, чтобы абстрагировать и инкапсулировать все обращения к источнику данных. Подобная реализация DAO управляет такими ресурсами базы данных, как соединения с источником данных.
Интерфейсы DAO очень легко адаптируются ко всем нижележащим механизмам источников данных, их не нужно заменять при изменениях в технологиях сохранения на более низких уровнях. Этот паттерн позволяет внедрять различные технологии доступа к данным, никак не затрагивая бизнес-логику корпоративного приложения. Рассмотрим рис. 8.1, чтобы лучше понять принципы паттерна DAO.
Как можно видеть на схеме, в паттерне участвуют следующие объекты.
BusinessObject — объект, работающий на бизнес-уровне, — клиент для уровня доступа к данным. Ему нужны данные, чтобы моделировать бизнес-процессы, а также подготавливать Java-объекты для вспомогательных функций или контроллеров приложения.
DataAccessObject — основной объект паттерна DAO. Скрывает от BusinessObject всю низкоуровневую реализацию работы нижележащей базы данных.
DataSource — тоже объект, содержащий всю низкоуровневую информацию о том, что именно представляет собой нижележащая база данных: RDBMS, неструктурированные файлы или XML.
TransferObject — объект, используемый как носитель информации. Применяется объектом DataAccessObject для возврата данных объекту BusinessObject.

Рассмотрим следующий пример паттерна DAO, в котором AccountDao представляет собой интерфейс объекта DataAccessObject, а AccountDaoImpl — класс, реализующий интерфейс AccountDao:
public interface AccountDao {
Integer totalAccountsByBranch(String branchName);
}
public class AccountDaoImpl extends JdbcDaoSupport implements
AccountDao {
@Override
public Integer totalAccountsByBranch(String branchName) {
String sql = "SELECT count(*) FROM Account WHERE branchName =
"+branchName;
return this.getJdbcTemplate().queryForObject(sql,
Integer.class);
}
}
Создание объектов DAO в Spring с помощью паттерна проектирования «Фабрика»
Как вы знаете, во фреймворке Spring задействуется множество паттернов проектирования. Паттерн «Фабрика» представляет собой порождающий паттерн проектирования и используется для создания объекта без раскрытия клиенту нижележащей логики, а также назначения вызывающей стороне нового объекта с помощью общего интерфейса или абстрактного класса. Благодаря паттернам проектирования «Фабричный метод» и «Абстрактная фабрика» можно достичь очень высокой гибкости паттерна DAO.
Выясним, где в нашем примере мы реализуем стратегию, в которой фабрика производит объекты DAO для реализации общей базы данных (рис. 8.2).

Вы можете увидеть на предыдущей схеме, что AccountDaoFactory производит объект AccountDao, то есть является для него фабрикой. Нижележащую базу данных можно заменить в любой момент, при этом бизнес-код менять не нужно — фабрика берет эту работу на себя. Spring поддерживает хранение всех DAO в фабрике компонентов, а также в фабрике DAO.
Паттерн «Отображение данных»
Фреймворк ORM обеспечивает отображение между объектами и реляционными базами данных, ведь объекты и таблицы реляционных баз данных по-разному хранят данные приложения. Кроме того, в объектах и таблицах есть различные механизмы структурирования данных. При использовании в приложении Spring любого ORM-решения, например Hibernate, JPA или JDO, нет нужды волноваться о механизме отображения между объектами и реляционными базами данных.
Рассмотрим рис. 8.3, чтобы лучше разобраться с паттерном «Отображение данных» (Data Mapper).

На схеме происходит отображение объекта Account в реляционную базу данных посредством интерфейса AccountMapper. AccountMapper играет в приложении роль посредника между Java-объектом и нижележащей базой данных. Рассмотрим еще один паттерн, используемый на уровне доступа к данным.
Паттерн «Модель предметной области»
Модель предметной области — объект, у которого есть и данные, и поведение, где поведение определяет бизнес-логику корпоративного приложения, а данные представляют собой информацию о результатах бизнеса. Модель предметной области объединяет данные и технологический процесс. В корпоративном приложении модель данных располагается ниже бизнес-уровня и определяет бизнес-логику, возвращая результаты бизнес-поведения. Рассмотрим следующую схему для большей ясности (рис. 8.4).

Как можно видеть на схеме, в приложении заданы две модели предметной области в соответствии с бизнес-требованиями. Бизнес-алгоритм перевода денег с одного счета на другой описан в классе TransferService. Классы TransferService и AccountService относятся к паттерну «Модель предметной области» в корпоративном приложении.
Прокси для паттерна «Отложенная загрузка»
«Отложенная загрузка» — паттерн проектирования, используемый некоторыми из ORM-решений, например Hibernate, в корпоративных приложениях, чтобы отложить инициализацию объекта до момента обращения к нему другого объекта, то есть момента, когда он понадобится. Цель этого паттерна проектирования состоит в оптимизации памяти в приложении. Паттерн проектирования «Отложенная загрузка» в Hibernate реализуется с помощью виртуального объекта-прокси. При демонстрации отложенной загрузки мы используем прокси, но он не относится к паттерну «Заместитель».
Паттерн «Шаблонный метод» для поддержки Hibernate в Spring
Фреймворк Spring предоставляет вспомогательный класс для доступа к данным на уровне DAO, основанный на паттерне проектирования «Шаблонный метод» GoF. Класс HibernateTemplate фреймворка Spring поддерживает такие операции баз данных, как save, create, delete и update. Этот класс гарантирует, что для каждой транзакции используется только один сеанс Hibernate.
Интеграция Hibernate со Spring
Hibernate — ORM-фреймворк сохранения с открытым исходным кодом, который не только обеспечивает отображение простых объектных взаимосвязей между Java-объектами и таблицами базы данных, но и предлагает множество продвинутых возможностей для повышения производительности приложения, а также помогает улучшить использование ресурсов, например с помощью кэширования, отложенной загрузки, немедленного извлечения данных и распределенного кэширования.
Spring обеспечивает полную поддержку интеграции с фреймворком Hibernate, у него имеется несколько встроенных библиотек, позволяющих задействовать Hibernate на все 100 %. Для задания настроек Hibernate в приложении можно воспользоваться паттерном внедрения зависимостей и контейнером IoC фреймворка Spring.
В следующем разделе мы выясним, как правильно настроить Hibernate в контейнере IoC фреймворка Spring.
Задание настроек объекта SessionFactory фреймворка Hibernate в контейнере Spring
Оптимальный подход к настройке Hibernate и других технологий сохранения в любом корпоративном приложении состоит в разделении бизнес-объектов с жестко «зашитыми» справочниками ресурсов, такими как DataSource в JDBC или SessionFactory в Hibernate. Эти ресурсы можно описать в виде компонентов в контейнере Spring. Но для доступа к ним бизнес-объектам необходимы ссылки на них. Рассмотрим следующий класс DAO, использующий объект SessionFactory для получения данных для приложения:
public class AccountDaoImpl implements AccountDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ...
}
Как можно видеть, класс DAO, AccountDaoImpl, следует паттерну внедрения зависимостей. Для доступа к данным в него внедряется объект SessionFactory фреймворка Hibernate, и он прекрасно чувствует себя в контейнере IoC Spring. Объект SessionFactory фреймворка Hibernate представляет собой объект-одиночку, он генерирует основной объект интерфейса Hibernate org.hibernate.Session. Объект SessionFactory управляет объектом Session, а также отвечает за его открытие и закрытие. Интерфейс Session содержит реальную функциональность доступа к данным — сохранения (save), обновления (update), удаления (delete) и загрузки (load) объектов из базы данных. В приложении объект класса AccountDaoImpl или любой другой репозиторий выполняет с помощью этого объекта Session все необходимые операции хранения данных.
Фреймворк Spring предоставляет встроенные модули Hibernate, так что вы можете использовать в своих приложениях компоненты SessionFactory Hibernate.
Компонент org.springframework.orm.hibernate5.LocalSessionFactoryBean представляет собой реализацию интерфейса FactoryBean фреймворка Spring. LocalSessionFactoryBean основан на паттерне «Абстрактная фабрика», он генерирует в приложении объект SessionFactory. Этот объект можно сконфигурировать в виде компонента в контексте Spring приложения следующим образом:
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource
dataSource) {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setPackagesToScan(new String[] {
"com.packt.patterninspring.chapter8.bankapp.model" });
Properties props = new Properties();
props.setProperty("dialect",
"org.hibernate.dialect.H2Dialect");
sfb.setHibernateProperties(props);
return sfb;
}
В этом коде мы сконфигурировали объект SessionFactory в виде компонента с помощью класса LocalSessionFactoryBean фреймворка Spring. Метод этого компонента принимает на входе объект типа DataSource в качестве аргумента, который определяет место и способ соединения с базой данных. Мы также указали, какой пакет просматривать, задав значение «com.packt.patterninspring.chapter8.bankapp.model» для свойства setPackagesToScan компонента LocalSessionFactoryBean, и задали свойство dialect компонента SessionFactory с помощью метода setHibernateProperties для указания того, с каким типом базы данных мы имеем дело в приложении.
Теперь, после настройки компонента SessionFactory Hibernate, в контексте приложения Spring посмотрим, как можно реализовать объекты доступа к данным для уровня сохранения нашего приложения.
Об авторе
Динеш Раджпут — главный редактор сайта Dineshonjava, технического блога, посвященного технологиям Java и Spring. На сайте размещены статьи на тему Java-технологий. Динеш — блогер, автор книг, c 2008 года энтузиаст Spring, сертифицированный специалист компании Pivotal (Pivotal Certified Spring Professional). Обладает более чем десятилетним опытом проектирования и разработки с использованием Java и Spring. Специализируется на работе с последней версией Spring Framework, Spring Boot, Spring Security, на создании REST API, архитектуре микросервисов, реактивном программировании, аспектно-ориентированном программировании с применением Spring, паттернах проектирования, Struts, Hibernate, веб-сервисах, Spring Batch, Cassandra, MongoDB, архитектуре веб-приложений.
В настоящее время Динеш работает менеджером по технологиям в одной из компаний, лидирующих в области создания программного обеспечения (ПО). Был разработчиком и руководителем команды в Bennett, Coleman & Co. Ltd, а до этого — ведущим разработчиком в Paytm. Динеш с восторгом относится к новейшим технологиям Java и любит писать о них в технических блогах. Является активным участником Java- и Spring-сообществ на различных форумах. Динеш — один из лучших специалистов по Java и Spring.
О рецензенте
Раджив Кумар Мохан обладает большим опытом разработки ПО и корпоративного обучения. На протяжении 18 лет он работал в таких крупнейших IT-компаниях, как IBM, Pentasoft, Sapient и Deft Infosystems. Начал карьеру как программист, руководил многими проектами.
Является экспертом в предметной области Java, J2EE и родственных фреймворках, Android, UI-технологиях. Сертифицирован компанией Sun в качестве Java-программиста (SCJP, Sun Certified Java Programmer) и веб-разработчика на Java (Sun Certified Web Component Developer, SCWCD). Раджив имеет четыре высших образования: в области информатики (Computer Science), прикладной информатики (Computer Applications), органической химии и делового администрирования (MBA). Является консультантом по подбору персонала и экспертом по обучению в HCL, Amdocs, Steria, TCS, Wipro, Oracle University, IBM, CSC, Genpact, Sapient Infosys и Capgemini.
Раджив — основатель фирмы SNS Infotech, расположенной в городе Большая Нойда. Кроме того, он работал в Национальном институте технологий моды (National Institute Of Fashion Technology, NIFT).
» Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок
Для Хаброжителей скидка 20% по купону — Spring