Документация разработчика Hibernate – Глава I. Доступ к базе данных

  • Tutorial
Представляю вашему вниманию перевод первой главы официальной документации 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 не обязательно хорошо владеть SQL, понимание основных концепций сыграет неплохую роль в быстром и полном освоении Hibernate. Лучшим подспорьем в освоении является понимание принципов моделирования данных. Информация по нижеследующим ссылкам может оказаться полезной


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оединения по требованию, основываясь на предоставленной конфигурации.

Пример 1.6. Открытие сессии

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).
Важно
Вы должны указать диалект SQL через свойство hibernate.dialect, когда используете эту утилиту, так как DDL сам по себе специфичен для каждого вендора. См подробности в Секции 1.3, “Диалекты”.

Перед тем, как 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=; Разделитель строк

Важно
Опции --naming и --namingdelegator, не должны использоваться вместе

Пример 1.8. Встраивание SchemaExport в ваше приложение

Configuration cfg = ....;
new SchemaExport(cfg).create(false, true);
  • +12
  • 23,9k
  • 3
Поделиться публикацией
Комментарии 3
    0
    Хм, начал сегодня смотреть Hibernate.
    А почему Вы решили переводить для этой версии? Она же с 2013 года не обновлялась, если я верно понимаю: http://docs.jboss.org/hibernate/orm/
    Пол-часа убил пытаясь заставить описанные Вами конфиги работать с актуальной 5.2 =(
      0
      Хотя нет, Github говорит что https://github.com/hibernate/hibernate-orm/releases/tag/4.2.19.Final была в апреле 2015.
      И тем не менее…
      0

      @samizdam
      Здесь преимущественно опирался на частоту использования. Не все перешли на 5ую, но многие ушли с 3ей.
      По 5-ой версии замечу, что там немного другой механизм конфигурирования, да и в целом документация там переработана по сравнению с 4.2.19
      По 4-ой версии между 4.2.19 и 4.3.11 не заметил особых изменений в документации, по этому в целом перевод может покрыть обе версии.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое