Компонентный подход в программировании


Управление данными приложения. Hibernate


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

Возможным решением этой задачи являются объектно-реляционные преобразователи (object-relation mappers, ORM), которые обеспечивают автоматическую синхронизацию между данными приложения в виде наборов связанных объектов и данными, хранящимися в системе управления базами данных (СУБД) в реляционном виде, т.е. в форме записей в нескольких таблицах, ссылающихся друг на друга с помощью внешних ключей.

Одним из наиболее широко применяемых и развитых в технологическом плане объектно-реляционных преобразователей является Hibernate [7,8,9].

Базовая парадигма, лежащая в основе избранного Hibernate подхода, — это использование объектов обычных классов Java (быть может, оформленных в соответствии с требованиями спецификации JavaBeans — с четко выделенными свойствами) в качестве объектного представления данных приложения. Такой подход даже имеет название-акроним POJO (plain old Java objects, простые старые Java-объекты), призванное показать его отличие от сложных техник построения компонентов, похожих на EJB.

Большое достоинство подобного подхода — возможность использовать один раз созданные наборы классов, представляющих понятия предметной области, в качестве модели данных любых приложений на основе Java, независимо от того, являются ли они распределенными или локальными, требуется ли в них синхронизация с базой данных и сохранение данных объектов или нет.


увеличить изображение
Рис. 15.2.  Реляционное представление данных о книгах и авторах

Например, для представления в объектном виде данных о книгах и их авторах, соответствующих показанной на рис. 15.2 группе таблиц, могут быть использованы представленные ниже классы:


import java.util.Set; import java.util.HashSet;

public class Author { private int id;

private String firstName; private String surname;

private Set books = new HashSet();

public int getId () { return this.id; } private void setId (int id) { this.id = id; }

public String getFirstName () { return this.firstName; } public void setFirstName (String firstName) { this.firstName = firstName; }

public String getSurname () { return this.surname; } public void setSurname (String surname) { this.surname = surname; }

public Set getBooks () { return this.books; } public void setBooks (Set books) { this.books = books; } }

public class Book { private int id;

private String title; private String isbn;

private Set authors = new HashSet();

public int getId () { return this.id; } private void setId (int id) { this.id = id; }

public String getIsbn () { return this.isbn; } public void setIsbn (String isbn) { this.isbn = isbn; }

public String getTitle () { return this.title; } public void setTitle (String title) { this.title = title; }

public Set getAuthors () { return this.authors; } public void setAuthors (Set authors) { this.authors = authors; } }

Пример 15.1.

Для определения отображения объектов этих классов в записи соответствующих таблиц используются конфигурационные файлы со следующим содержанием. Первый фрагмент представляет собой описание отображения объектов класса Author на записи таблицы Authors, которое обычно помещается в файл Author.hbm.xml:

<hibernate-mapping> <class name="Author" table="Authors"> <id name="id" column="ID"> <generator class="increment"/> </id> <property name="firstName" column="FirstName"/> <property name="surname"/ column="Surname"> <set name="books" table="BookAuthors" inverse="true"> <key column="AuthorID"/> <many-to-many column="BookID" class="Book"/> </set> </class> </hibernate-mapping>



Второй фрагмент представляет собой содержание аналогичного файла Book.hbm.xml, описывающего отображение объектов класса Book на записи таблицы Books.

<hibernate-mapping> <class name="Book" table="Books"> <id name="id" column="ID"> <generator class="increment"/> </id> <property name="title" column="Title"/> <property name="isbn"/ column="ISBN"> <set name="authors" table="BookAuthors" inverse="true"> <key column="BookID"/> <many-to-many column="AuthorID" class="Author"/> </set> </class> </hibernate-mapping>

При использовании объектов указанных классов в рамках приложения на основе Hibernate обеспечивается автоматическая синхронизация данных объектов с данными соответствующих записей, а также автоматическая поддержка описанного отношения типа "многие-ко-многим".

Кроме того, Hibernate поддерживает удобные средства для описания сложных соответствий между объектами и записями таблиц при использовании наследования. Так, легко могут быть поддержаны: отображение данных всех объектов классов-наследников в одну таблицу, отображение объектов разных классов-наследников в разные таблицы, отображение данных полей общего класса-предка в одну таблицу, а данных классов-наследников — в разные таблицы, а также смешанные стратегии подобных отображений.

В приложениях на основе Hibernate объекты одного и того же класса могут быть как хранимыми, т.е. представляющими данные, хранящиеся в базе данных, так и временными, не имеющими соответствующих записей в базе данных. Перевод объекта из одного из этих видов в другой осуществляется при помощи всего лишь одного вызова метода вспомогательного класса среды Hibernate.

C помощью дополнительной службы NHibernate [7] возможности среды Hibernate могут быть использованы и из приложений на базе .NET.


Содержание раздела