SPRING-SOURCE.RU

Доступ к данным используя Spring Framework: Hibernate template

Извлечение данных из разнородных серверов баз данных в Data Access Layer (DAL) стало обычным при разработке приложений корпоративного уровня. Это в свою очередь приводит к написанию специального серверного кода на уровне DAL и подключению в логику конфигурации, которая определяет, какой сервер будет использоваться при запуске. Для приложений средней сложности это хорошо. Однако, при возрастании сложности, серверный код и конфигурация, как правило, становятся частью инфраструктуры, которая запускает приложение, что в свою очередь добавляет чрезмерную сложность в применении. Именно при таком сценарии Object Relational Mapping (ORM) фреймворки выходят в свет. Эти фреймворки динамически генерируют нужный SQL для нужной системы базы данных. Используя ORM фреймворки, нужная система базы данных может быть установлена через конфигурационный файл. Таким образом они хорошо заботятся о логической конфигурации. В этой статье мы будем работать с Hibernate, с одним из более часто используемых ORM фреймворков.

Хотя ORM фреймворк, такой как, Hibernate прячет большинство сложностей связанных с базами данных, фреймворк имеет свою инфраструктуру управляющую сессиями и транзакциями. Такие требования могут хорошо управляться через использование другого фреймворка, который использует инъекцию зависимостей для управления Hibernate сессиями и транзакциями. В нашем случае это будет Spring фреймворк. Он предоставляет класс интеграции с Hibernate через HibernateTemaple. Это аналог JdbcTemaplate, который используется для связи с JDBC API. В этом обсуждении мы будем использоваться HibernateTemaplate для интеграции Hibernate и Spring Framework. Первая часть будет вводной в HibernateTemplate. Во второй части мы рассмотрим шаги показывающие как соединить Hibernate и Spring Framework. В последней части мы рассмотрим приложение, которое будет использувать шаги предыдущего раздела.

HibernateTemplate

Spring Framework предоставляет различные подходы для интеграции с Hibernate. Тем не менее, мы наиболее часто будем использовать подход, использующий HibernateTemplate. Есть две основные причины:

Скрывает детали управления сессиями и транзакциями
HibernateTemplate класс скрывает трудности управления сессиями и транзакциями при использовании Hibernate для доступа к данным. Нужно только иницилизировать HibernateTemplate путем передачи экземпляра SessionFactory. Spring Framework берет на себя беспокойство за детали связанные с сессиями и транзакциями. Это помагает устранить инфраструктурный код, который может вносить суматоху при увеличении сложности.

Предоставляет подход основанный на шаблонах
HibernateTemplate, так же как и JdbcTemplate, предоставляет шаблонный подход для доступа к данным. Когда вы используете HibernateTemplate, вы будете работать с callbacks. Обратные вызовы - это единственный механизм в шаблонном подходе, который уведомляет шаблон запускать нужную задачу. Преимущество наличия обратного вызова в том, что там только одна точка входа в слой доступа к данным. И эта точка входа определяется шаблоном, в этом случае HibernateTemplate.

Теперь, когда мы обсудили преимущества и причины использования HibernateTemplate, мы перейдем к его функциональности. API может быть резделено на следующие пункты:

  1. Удобство/вспомогательные методы
  2. Методы шаблона

Удобство/вспомогательные методы
Hibernate имеет API который упрощает CRUD (Create, Retrieve, Update, Delete) операции. Вспомогательные методы у HibernateTemplate составляют как бы обертку для того чтобы методы шаблона могли заботиться о сессии и управлении транзакциями. Как разработчик, вы будете напрямую делать вызовы к вспомогательным методам без явного открытия и закрытия сессий. Вспомогательные методы включают find(), saveOrUpdate(), delete() итп.

Методы шаблона
Шаблон или методы обратного вызова имеют важное значение для HibernateTemplate. Существует четыре главных метода шаблона:

Из них Execute используется чаще всего. Для использования любого из этих методов достаточно создать экземпляр HibernateTemplate, передавая экземпляр SessionFactory в конструктор HibernateTemplate. Все формы Execute метода берут экземпляр HibernateCallback класса и выполняют логику доступа к данным, содержащимся в экземпляре класса расширяющего HibernateCallback.

Использование HibernateTemplate шаг за шагом

Существует три основных шага для использования HibernateTemplate:

  1. Разработка Data Access Object (DAO)
  2. Конфигурация DAO и соответствующих объектов Hibernate
  3. Разработка клиента
Нужно иметь ввиду, что все эти шаги покрывают только Spring Framework зону Spring-Hibernate интеграции.

1. Разработка Data Access Object (DAO)
DAO - это POJO, содержащий логику доступа к данным. Для использования DAO с HibernateTemplate нужно учесть следующие требования:

Сеттер для SessionFactory
Нужно передать экземпляр SessionFactory для инициизации HibernateTemplate. HibernateTemplate это часть Spring Framework и можно использовать инъекцию зависимостей для доставки экземпляра. Однако, чтобы это сделать, нужно создать setter для SessionFactory в DAO. Пример:

                        
private HibernateTemplate hibernateTemplate;

public void setSessionFactory(SessionFactory sessionFactory){
	this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
		

Метод или методы, возвращающие данные
Метод, возвращающий данные может быть двух типов:

Как обсуждалось ранее, вспомогательные методы позволяют получать доступ к данным без использования Hibernate API. Эти методы закутывают большинство из наиболее часто успользуемых finder, loader и updater API Hibernate. Например, метод, который находит продукт по категории использует Hibernate Query Language (HQL):

                        
public Collection loadProductsByCategory(String category) throws 
	DataAccessException {
		return this.hibernateTemplate.find("from test.Product product where 
		product.category=?", category);
}
		

Будут ситуации, где будет недостаточно одних вспомогательных методов так как они не раскрывают/предоставляют определенных API Hibernate. В таких случаях, могу быть использованы callbacks (обратный вызов) или template (шаблон) методы. HibernateTemplate предоставляет интерфейс Session через эти методы шаблоноа. Для того чтобы использовать методы шаблона, нужно передать экземпляр класса, который наследуется от класса HibernateCallback и замещает doInHibernate метод. Вместо создания отдельного класса и передачи его экземпляра методу шаблона, можно использовать анонимный класс чтобы сделать тоже самое, что показано ниже:

                        
public Collection loadProductsByCategory(final String category) throws 
	DataAccessException {
		return this.hibernateTemplate.execute(new HibernateCallback() 
		{

			public Object doInHibernate(Session session)
			{
				Criteria criteria = session.createCriteria(Product.class);
				criteria.add(Expression.eq("category", category));
				criteria.setMaxResults(6);
				return criteria.list();
			}
		}
		);
	}
		

Этот пример использует execute() метод шаблона для работы с запросом, который не доступен при работе с вспомогательными методами.

2. Конфигурация DAO и соответствующих объектов Hibernate
DAO должен быть настроен так, чтобы Spring Framework мог знать об Hibernate артифактах (конфигурационные файлы, hbm файлы, ORM классы). Именно благодаря конфигурации Spring Framework, передающей экземпляр SessionFactory в setter метод DAO. Это можно сделать в два этапа:

Настройка SessionFactory
Hibernate использует SessionFactory для управления соединениями и сессиями на сервере базы данных. Следовательно, для настройки SessionFactory, нужно настроить доступ к серверу базы данных. Настройка делается в XML файле. Имя файла может быть любым. Шаги:

  1. Первым шагом будет настройка data source (источника данных), который используется SessionFactory. В Spring Framework, каждый ресурс это бин. И так, нам нужно объявить бин, который привязан к одной из реализаций DataSource. Чаще всего используется org.apache.commons.dbcp.BasicDataSource реализация. Вот пример бина привязанного к BasicDataSource:

                            
    <bean id="testDataSource" 
    class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close">
    :
    :
    </bean>
    		

    После того как мы сопоставили бин, следующим шагом будет предоставление данных о соединении, таких как имя, адрес сервера, имя пользователя и пароль. Это может быть сделано через <property> тэг. Он имеет два атрибута - имя и значение. Пример:

                            
    <bean id="testDataSource" 
    class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close">
    
    <property 
    name="driverClassName" 
    value="org.hsqldb.jdbcDriver"/>
    :
    :
    </bean>
    		

    В примере выше имя драйвера сопоставляется с источником данных.
  2. Следующий шаг - настройка SessionFactory. Чтобы настроит SessionFactory нужно следовать четырем вещам:
    Объявляем реализацию SessionFactory
    Например, свяжем бин с LocalSessionFactoryBean, который является реализацией SessionFactory:

                            
    <bean id="mySessionFactory" 
    class="org.springframework.orm.hibernate3.
    LocalSessionFactoryBean">
    :
    :
    </bean>
    		

    Передаем ссылку на источник данных
    SessionFactory требует источника данных с которым он будет соединяться.

                            
    <bean id="mySessionFactory" 
    class="org.springframework.orm.hibernate3.
    LocalSessionFactoryBean">
    
    <property name="dataSource" ref="testDataSource"/>
    :
    :
    </bean>
    		

    Привязываем Hibernate артифакты
    HBM файлы, которые содержат детали ORM файлов нужно присоединять на этом этапе.

                            
    <property name="mappingResources">
    <list>
    <value>product.hbm.xml</value>
    </list>
    </property>
    		

    Привязываем диалект (dialect)
    Последним шагом будет привязывание диалекта.

                            
    <property name="hibernateProperties">
    <value>
    hibernate.dialect=org.hibernate.dialect.HSQLDialect
    </value>
    </property>
    		

Настройка DAO
Следуем следующим шагам для настройки DAO:

Конфигурация клиента
Шаги для разработки клиента:

Получение экземпляра DAO
DAO может быть получен через реализацию BeanFactory:

                        
Resource res = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(res);
ProductDAO dao = (ProductDAO)factory.get("myProductDAO");
		

Вызов метода доступа к данным
DAO экземпляр извлекается, метод доступа к данным может вызываться также как любые другие методы. Сессии и транзакции будут управляться через HibernateTemaplate, так чтобы клиент не заботился об этом.

                        
Collection products = dao.loadProductsByCategory("Cathode");