Представляю вашему вниманию перевод первой главы официальной документации Hibernate.
Перевод статьи актуален для версии Hibernate 4.2.19.Final
Cледующая глава — Документация разработчика Hibernate – Глава II. Транзакции и контроль многопоточности
Содержание
 Предисловие
 1. Доступ к базе данных
  1.1. Подключение
   1.1.1. Конфигурация
   1.1.2. Получение JDBC-соединения
  1.2. Пулинг соединений (Connection pooling)
   1.2.1. Пулинг с помощью с3p0
   1.2.2. Пулинг с помощью Proxool
   1.2.3. Получение соединений от сервера приложений, через JNDI
   1.2.4. Прочее по конфигурации соединений
   1.2.5. Необязательные свойства конфигурации
  1.3. Диалекты
   1.3.1. Указание диалекта для использования
   1.3.2. Разрешение диалекта
  1.4. Автоматическая генерация схемы при помощи Schema Export
   1.4.1. Кастомизация файлов маппинга (Customizing the mapping files)
   1.4.2. Запуск инструмента SchemaExport
Предисловие
Работа как с объектно-ориентированным ПО, так и с реляционными базами данных (далее БД, прим.перев.) может быть весьма обременительной и затратной с точки зрения потраченного времени. Затраты на разработку существенно выше из-за несовпадения парадигм представления данных в объектах и реляционных БД. Hibernate является решением т.н. объектно-реляционного проецирования для Java. Термин объектно-реляционного проецирования отноcится к технике проецирования (маппинга) данных из объектной модели представления к реляционной модели представления (и наоборот). См. en.wikipedia.org/wiki/Object-relational_mapping для более подробного ознакомления.
Hibernate не только заботится о проецировании Java-классов в таблицы БД (а также проецировании базовых типов Java к типам SQL), но и предоставляет механизмы формирования запросов и выборок данных. Он может существенно снизить время на разработку, которая в старом стиле велась путем ручной работы с данными с использованием SQL и JDBC. Главная цель архитектурного дизайна Hibernate – избавление разработчика от ежедневных задач работы с данными БД, путем избавления от нужд написания собственной логики работы с данными через SQL и JDBC. Однако, в отличие от других persistence-решений, Hibernate не скрывает от вас возможность использовать всю мощь SQL, и гарантирует, что ваши вложения в реляционные технологии и знания по-прежнему имеют силу.
Hibernate может быть не лучшим решением для приложений, хранящих всю свою бизнес-логику в хранимых процедурах, оно скорее подходит для объектно-ориентированных моделей и логики в среднем (бизнес) слое приложения, написанном на Java. Однако, Hibernate совершенно точно может помочь вам избавиться или инкапсулировать логику специфического SQL-кода, а также справиться с повседневными задачами трансляции результатов ваших запросов из табличного представления в граф объектов.
1. Доступ к базе данных
1.1. Подключение
Hibernate соединяется с базой от имени вашего приложения. Соединение может осуществляться через различного рода механизмы, а именно:
- Встроенный пул соединений
- javax.sql.DataSource
- Пулы соединений, также можно использовать сторонние открытые решения для пулов:
- c3p0
- proxool
- Собственноручно созданные приложением JDBC-соединения. Это нерекомендуемый подход и единственная причина его использования – работа с устаревшим (legacy) окружением.
Hibernate получает JDBC-соединения по мере необходимости через интерфейс org.hibernate.service.jdbc.connections.spi.ConnectionProvider. Приложения могут также предоставлять свои реализации интерфейса org.hibernate.service.jdbc.connections.spi.ConnectionProvider для определения кастомного подхода к предоставлению соединений Hibernate’у. (Из другого пула соединений, например)
1.1.1. Конфигурация
Вы можете сконфигурировать соединение к базе данных, используя property-файл, через XML-дескриптор развертывания или программно.
Пример 1.1. hibernate.properties для пула соединений c3p0
hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQL82Dialect
Пример 1.2. hibernate.cfg.xml для соединения к встраиваемой базе данных HSQL
<?xml version='1.0' encoding='utf-8'?>
<hibernate-configuration
xmlns="http://www.hibernate.org/xsd/hibernate-configuration"
xsi:schemaLocation="http://www.hibernate.org/xsd/hibernate-configuration hibernate-configuration-4.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml"/>
</session-factory>
</hibernate-configuration>
1.1.1.1. Программная конфигурация
Экземпляр объекта org.hibernate.cfg.Configuration представляет полный набор типов маппингов на базу данных. Объект org.hibernate.cfg.Configuration создает иммутабельный объект org.hibernate.SessionFactory, и компилирует маппинги из различных XML-файлов. Вы можете указать файлы для маппинга напрямую, или Hibernate может найти их за вас.
Пример 1.3. Указание файлов для маппинга напрямую
Вы можете получить объект org.hibernate.cfg.Configuration, cоздав его и указав XML-документы для маппинга напрямую. Если файлы для маппинга находятся в classpath, используйте метод addResource().
Configuration cfg = new Configuration()
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");
Пример 1.4. Hibernate находит файлы за вас
Метод addClass() указывает Hibernate искать mapping-файлы через classpath, основываясь на имени класса, при этом избавляя вас от необходимости указывать имена файлов самому. В следующем примере, он ищет org/hibernate/auction/Item.hbm.xml и org/hibernate/auction/Bid.hbm.xml.
Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class);
Пример 1.5. Указание свойств конфигурации
Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class)
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")
.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")
.setProperty("hibernate.order_updates", "true");
Другие способы программной конфигурации Hibernate
- Передача экземпляра java.util.Properties в Configuration.setProperties().
- Установка системного свойства, используя java -Dproperty=value
1.1.2. Получение JDBC-соединения
После того, как вы сконфигурируете Основные jdbc-свойства Hibernate, вы можете использовать метод openSession класса org.hibernate.SessionFactory для открытия сессий. Сессии откроют JDBC-cоединения по требованию, основываясь на предоставленной конфигурации.
Session session = sessions.openSession();
Основные jdbc-cвойства Hibernate
- hibernate.connection.driver_class
- hibernate.connection.url
- hibernate.connection.username
- hibernate.connection.password
- hibernate.connection.pool_size
1.2. Пулинг соединений (Connection pooling)
Внутренний алгоритм пулинга соединений в Hibernate довольно рудиментарен, и нужен, по большей части, для разработки и тестирования. Используйте сторонние (3rd party) пулы для лучшей производительности и стабильности. Для использования 3rd party пула, замените значение свойства hibernate.connection.pool_size на соответствующие специфике вашего выбранного пула. Это отключит использование встроенного пула Hibernate.
1.2.1. Пулинг с помощью c3p0
C3P0 – опенсорсный пул JDBC-соединений, распространяемый вместе с Hibernate в директории lib/. Hibernate будет использовать свой собственный org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider для пулинга соединений, при настройке свойств hibernate.c3p0.*
Важные конфигурационные свойства для c3p0
- hibernate.c3p0.min_size
- hibernate.c3p0.max_size
- hibernate.c3p0.timeout
- hibernate.c3p0.max_statements
1.2.2. Пулинг с помощью Proxool
Proxool — другой опенсорсный пул, распространяемый вместе с Hibernate в директории lib/. Hibernate будет использовать свой собственный org.hibernate.service.jdbc.connections.internal.ProxoolConnectionProvider для пулинга соединений при соответствующей настройке hibernate.proxool.*. В отличие от c3p0, proxool требует некоторых дополнительных параметров настройки, которые описаны в документации, доступной на proxool.sourceforge.net/configure.html.
Таблица 1.1. Важные конфигурационные свойства для пула соединений Proxool
Свойство | Описание |
---|---|
hibernate.proxool.xml | Сконфигурируйте провайдер Proxool, используя указанный файл XML (.xml добавляется автоматически) |
hibernate.proxool.properties | Сконфигурируйте провайдер Proxool, используя указанный property-файл (.properties добавляется автоматически) |
hibernate.proxool.existing_pool | Конфигурировать ли провайдер Proxool из существующего пула |
hibernate.proxool.pool_alias | Псевдоним пула Proxool. Необходим. |
1.2.3. Получение соединений от сервера приложений, через JNDI
Для использования Hibernate внутри сервера приложений, настройте Hibernate для получения соединений от javax.sql.Datasource, зарегистрированном в JNDI, установив по крайней мере одно из следующих свойств:
Важные свойства для источников данных JNDI
- hibernate.connection.datasource (необходимо)
- hibernate.jndi.url
- hibernate.jndi.class
- hibernate.connection.username
- hibernate.connection.password
JDBC-соединения, полученные из источника данных JNDI, автоматически участвуют в container-managed транзакциях сервера приложений.
1.2.4. Прочее по конфигурации соединений
Вы можете передавать произвольные свойства соединения, добавляя перед ними hibernate.connection. К примеру, для указания свойства charSet используйте имя hibernate.connection.charSet.
Вы можете определить свою стратегию для получения JDBC-соединений, реализовав интерфейс org.hibernate.service.jdbc.connections.spi.ConnectionProvider, и указав вашу пользовательскую реализацию при помощи свойства hibernate.connection.provider_class
1.2.5. Необязательные свойства конфигурации
В дополнение к свойствам, перечисленным выше, Hibernate включает в себя множество других параметров. См. более подробный список на http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html_single/.
1.3. Диалекты
Хотя SQL относительно стандартизирован, каждый поставщик СУБД использует свое подмножество поддерживаемых синтаксисов. У этого есть и другой термин, называемый диалектом. Hibernate поддерживает различные вариации диалектов через класс org.hibernate.dialect.Dialect и различные подклассы для каждого vendor-диалекта.
Таблица 1.2. Поддерживаемые диалекты СУБД
1.3.1. Указание диалекта для использования
Разработчик может вручную указать диалект для использования, указав в свойстве hibernate.dialect нужное имя подкласса org.hibernate.dialect.Dialect.
1.3.2. Разрешение диалекта
Заранее предположив, что org.hibernate.service.jdbc.connections.spi.ConnectionProvider был настроен, Hibernate попытается автоматически определить диалект, основываясь на java.sql.DatabaseMetaData получаемым из объекта java.sql.Connection, который в свою очередь достается из org.hibernate.service.jdbc.connections.spi.ConnectionProvider.
Эта функциональность предоставляется экземплярами org.hibernate.service.jdbc.dialect.spi.DialectResolver, зарегистрированными cамим фреймворком. Hibernate идет вместе со стандартным набором распознаваний. Если в вашем приложении требуются дополнительные возможности распознавания диалекта, вполне возможно зарегистрировать кастомную реализацию org.hibernate.service.jdbc.dialect.spi.DialectResolver, как показано ниже
Зарегистрированные реализации org.hibernate.service.jdbc.dialect.spi.DialectResolver добавляются во внутренний список resolverов, так что они имеют приоритет над уже ранее зарегистрированными resolver’ами, а также над стандартными.
1.4. Автоматическая генерация схемы при помощи SchemaExport
SchemaExport – утилита Hibernate, которая генерит DDL-скрипты из ваших файлов маппинга. Сгенерированная схема включает в себя ограничения ссылочной целостности (referential integrity constraints), основные и внешние ключи для сущностей и таблиц коллекций. Она также создает таблицы для последовательностей(sequences) и спроецированных id-генераторов (identity generators).
Перед тем, как Hibernate сможет сгенерировать вашу схему, вы должны кастомизировать ваши файлы маппинга.
1.4.1. Кастомизация файлов маппинга (Customizing the mapping files)
Hibernate предоставляет ряд элементов и атрибутов для ваших файлов маппинга. Они перечислены в Таблице 1.3, “Элементы и аттрибуты, предоставляемые для кастомизации файлов маппинга”, а логический порядок кастомизации представлен в Процедуре 1.1, “Кастомизация схемы”.
Таблица 1.3. Элементы и атрибуты, предоставляемые для кастомизации файлов маппинга
Имя | Тип значения | Описание |
---|---|---|
length | number | Длина колонки |
precision | number | Десятичная точность колонки |
scale | number | Десятичный масштаб колонки |
not-null | true или false | Может ли колонка содержать null-значения |
unique | true или false | Содержит ли колонка только уникальные значения |
index | string | Имя многоколоночного индекса |
unique-key | string | Имя многоколоночного ограничения на уникальность |
foreign-key | string | Имя ограничения внешнего ключа, генерируемое для ассоциаций. Это относится к <one-to-one>, <many-to-one>, <key>, и <many-to-many> элементам. inverse=«true» пропускаются SchemaExport. |
sql-type | string | Переопределяет тип колонки по-умолчанию. Это относится только к элементу <column>. |
default | string | Значение по-умолчанию для колонки |
check | string | SQL ограничения (SQL check constraint) либо на колонку, либо на таблицу |
Процедура 1.1. Кастомизация схемы
1. Установка длины, точности, и масштаба элементов маппинга.
Множество элементов маппинга определяют необязательные атрибуты, такие как длина, точность, и масштаб.
<property name="zip" length="5"/>
<property name="balance" precision="12" scale="2"/>
2. Установка not-null, UNIQUE, unique-key аттрибутов.
not-null и UNIQUE атрибуты генерируют ограничения на табличные колонки.
Атрибут unique-key группирует колонки в единое ограничение по уникальности. Атрибут переопределяет имя любого сгенерированного ограничения уникальности.
<many-to-one name="bar" column="barId" not-null="true"/>
<element column="serialNumber" type="long" not-null="true" unique="true"/>
<many-to-one name="org" column="orgId" unique-key="OrgEmployeeId"/>
<property name="employeeId" unique-key="OrgEmployee"/>
3. Установка index и foreign-key аттрибутов.
Атрибут index указывает имя индекса для его создания, используя спроецированную колонку или колонки. Вы можете сгруппировать несколько колонок по одному индексу, указав в каждой из них имя одного и того же индекса.
Атрибут внешнего ключа (foreign key) переопределяет имя любого сгенерированного ограничения внешнего ключа.
<many-to-one name="bar" column="barId" foreign-key="FKFooBar"/>
4. Установка дочерних <column>-элементов.
Множество элементов маппинга допускают использование дочерних <column> элементов. Это бывает полезно для маппинга типов, включающих в себя несколько колонок.
<property name="name" type="my.customtypes.Name"/>
<column name="last" not-null="true" index="bar_idx" length="30"/>
<column name="first" not-null="true" index="bar_idx" length="20"/>
<column name="initial"/>
</property>
5. Установка атрибута default.
Атрибут default представляет собой значение по-умолчанию для колонки. Добавьте значение к спроецированному свойству перед сохранением нового экземпляра класса.
<property name="credits" type="integer" insert="false">
<column name="credits" default="10"/>
</property>
<version name="version" type="integer" insert="false">
<column name="version" default="0"/>
</version>
6. Установка атрибута sql-type.
Используйте атрибут sql-type для переопределения маппинга по-умолчанию для типов Java на типы SQL.
<property name="balance" type="float">
<column name="balance" sql-type="decimal(13,3)"/>
</property>
7. Установка атрибута check.
Используйте атрибут check для указания ограничения check.
<property name="foo" type="integer">
<column name="foo" check="foo > 10"/>
</property>
<class name="Foo" table="foos" check="bar < 100.0">
...
<property name="bar" type="float"/>
</class>
8.Добавление <comment> элементов к вашей схеме.
Используйте элемент <comment> для указания комментариев для сгенерированной схемы.
<class name="Customer" table="CurCust">
<comment>Current customers only</comment>
...
</class>
1.4.2. Запуск инструмента SchemaExport
Инструмент SchemaExport записывает DDL-скрипт в стандартный поток вывода, исполняет DDL, или и то, и другое сразу.
Пример 1.7. Синтаксис SchemaExport
java -cp hibernate_classpaths org.hibernate.tool.hbm2ddl.SchemaExport options mapping_files
Таблица 1.4. Опции SchemaExport
Опция | Описание |
---|---|
--quiet | Не выводить скрипт в стандартный поток вывода |
--drop | Только удалять таблицы |
--create | Только создавать таблицы |
--text | Не экспортировать в БД |
--output=my_schema.ddl | Вывести скрипт в указанный файл |
--naming=eg.MyNamingStrategy | выбор NamingStrategy |
--namingdelegator=eg.MyNamingStrategyDelegator | выбор NamingStrategyDelegator |
--config=hibernate.cfg.xml | Чтение конфигурации Hibernate из файла XML |
--properties=hibernate.properties | Чтение свойств БД из указанного файла |
--format | Опрятное форматирование SQL |
--delimiter=; | Разделитель строк |
Пример 1.8. Встраивание SchemaExport в ваше приложение
Configuration cfg = ....;
new SchemaExport(cfg).create(false, true);
Автор: otvorot2008