Автор: Дзен и искусство компьютерного программирования
1. Общие сведения
Hibernate — это мощная среда сохранения Java. Он предоставляет разработчикам инструмент объектно-реляционного сопоставления, позволяющий сопоставлять объектно-ориентированные модели с реляционными базами данных посредством простой настройки. Hibernate позволяет легко получать доступ к реляционным базам данных, управлять ими, оптимизировать и синхронизировать их. Благодаря простоте использования, высокой производительности и гибкости Hibernate стал самой популярной платформой ORM в области программирования на Java. В этой серии статей будут обсуждаться основные концепции и технические принципы Hibernate, а также способы применения Hibernate для решения практических задач в реальных проектах.
2. Основные понятия и связи
2.1 Обзор режима гибернации
Hibernate — это платформа J2EE с открытым исходным кодом для платформы ORM (объектно-реляционное сопоставление, объектно-реляционное сопоставление). В Hibernate мы можем использовать технологию объектно-реляционного сопоставления для хранения объектов приложения в реляционной базе данных. Через Hibernate мы можем изменять данные в базе данных во время работы программы без перекомпиляции или перезапуска сервера. Таким образом, Hibernate предоставляет метод программирования, аналогичный объектно-ориентированному, что позволяет нам упростить доступ к базе данных.
Hibernate имеет следующие основные функции:
Объектное/реляционное сопоставление: Hibernate позволяет таблицам базы данных соответствовать объектам в программе, и каждый объект можно легко получить, обновить, удалить или добавить в базу данных.
Генерация SQL: Hibernate может автоматически генерировать соответствующие операторы SQL на основе изменений, внесенных в объекты приложения, тем самым упрощая операции чтения и записи данных.
Встроенное управление транзакциями в рамках: Hibernate предоставляет механизм управления транзакциями, который может упростить процесс обработки данных на уровне бизнес-логики и уровне персистентности.
Кэширование: Hibernate поддерживает кэширование на уровне приложения, что может повысить эффективность запросов и сократить количество обращений к базе данных.
Query DSL: Hibernate поддерживает язык запросов HQL (Hibernate Query Language), который может писать сложные запросы в стиле SQL.
2.2 Спящая архитектура
Архитектура Hibernate разделена на три уровня:
- Базовый уровень: Базовый уровень включает в себя уровень объекта домена и уровень службы сохраняемости. Уровень объектов домена определяет классы сущностей, и объекты на этом уровне имеют однозначное соответствие с полями таблицы в реляционной базе данных; уровень службы персистентности инкапсулирует базовый API JDBC. Когда операции CRUD выполняются над объектами домена, сначала они преобразуются в инструкции SQL, затем выполняются инструкции SQL и возвращаются результаты выполнения.
- Уровень сопоставления: Уровень сопоставления отвечает за определение файлов сопоставления. Файл сопоставления определяет отношения, ограничения и другую информацию между объектами домена и таблицами базы данных, помогая Hibernate реализовать функции ORM.
- Уровень интеграции платформы: Уровень интеграции платформы реализует интерфейс интеграции между платформой Hibernate и другими платформами. Например, Spring и Struts2 можно интегрировать с Hibernate через интерфейс, предоставляемый Hibernate.
2.3 Конфигурация спящего режима
Файл конфигурации Hibernate hibernate.cfg.xml разделен на четыре части:
- Настройки SessionFactory: SessionFactory представляет основной класс Hibernate, включая пулы соединений, стратегии безопасности потоков и некоторые настройки Hibernate. SessionFactory состоит из файлов конфигурации и сопоставления Hibernate.
- Настройки JDBC ConnectionProvider: ConnectionProvider реализует стратегию получения и выпуска соединений JDBC.
- Настройки TransactionManager: TransactionManager реализует стратегии управления транзакциями.
- Настройки пути к классам. Настройки пути к классам содержат путь к пакету jar, необходимый для Hibernate.
2.4 Классы сущностей и ассоциации
Класс сущности: класс сущности Hibernate — это класс типа JavaBean, который содержит некоторые атрибуты (поля).Доступ к этим значениям атрибутов можно получить через геттеры и сеттеры, и их можно использовать напрямую или сериализовать в формат JSON или XML. Примеры классов сущностей:
public class Customer {
private int id;
private String name;
// getters and setters omitted for brevity
public void addOrder(Order order){
orders.add(order);
}
public Collection<Order> getOrders(){
return orders;
}
}
@Entity
public class Order {
@Id
private int orderId;
private Date date;
// many-to-one relationship with customer
@OneToOne
@JoinColumn(name="customer_id")
private Customer customer;
// getters and setters omitted for brevity
}
Аннотации для классов сущностей:
@Entity
: эта аннотация отмечается на классе, указывая, что класс является классом сущности.@Id
: эта аннотация отмечается на атрибуте первичного ключа, указывая, что значение этого атрибута однозначно идентифицирует объект сущности.@Column
: эта аннотация используется для определения имен столбцов и других связанных свойств.@OneToMany
: эта аннотация определяет связь «один-ко-многим».@ManyToOne
: эта аннотация определяет отношение «многие к одному».@ManyToMany
: эта аннотация определяет связь «многие ко многим».@JoinTable
: эта аннотация определяет промежуточную таблицу.@JoinColumn
: эта аннотация определяет внешний ключ основной таблицы.
2.5 Язык запросов HQL
HQL (Hibernate Query Language) — это объектно-ориентированный язык запросов, предоставляемый Hibernate. HQL позволяет легко выполнять сложные запросы и избегать объединения операторов SQL.
Пример синтаксиса HQL:
from Employee as e where e.salary > :minSalary
and e.department = 'IT'
group by e.department
order by e.salary desc
Процесс запроса HQL:
- Используйте ключевое слово «from», чтобы указать имя запрашиваемого класса сущности.
- Ключевое слово «as» создает псевдоним класса.
- Используйте предложение «где», чтобы указать критерии поиска.
- Имя параметра после символа «:» используется для привязки значения параметра.
- Для группировки используется предложение «group by».
- Предложение «order by» используется для сортировки.
3. Подробное объяснение основных принципов алгоритма, конкретных этапов работы и формул математической модели.
3.1 Основные принципы ORM
ORM (объектно-реляционное сопоставление) — это технология программирования, используемая для преобразования таблиц реляционной базы данных в объектно-ориентированные модели, чтобы данными базы данных можно было манипулировать объектно-ориентированным способом.
Существует две основные формы объектно-реляционного отображения:
- Сопоставление «один к одному». Это сопоставление означает, что между двумя объектами сущностей существует связь «один к одному». Например, один объект сущности соответствует записи в базе данных, а другой объект сущности также соответствует записи в базе данных.
- Сопоставление «один ко многим». Это сопоставление означает, что один объект сущности соответствует записям в нескольких таблицах реляционной базы данных. Например, объект сущности соответствует записи в таблице заказов, а таблица заказов может содержать записи из нескольких таблиц информации о продукте.
3.2 Процесс сохранения данных в спящем режиме
Рабочий процесс Hibernate показан на рисунке ниже:
- Создание объекта Session: Hibernate использует объект SessionFactory для создания объекта Session, который является точкой входа в Hibernate.
- Выполнение операций добавления, удаления, изменения и запроса. Пользователь выполняет операции добавления, удаления, изменения и запроса, вызывая метод Session, а Hibernate выполняет соответствующие операции с базой данных через базовый драйвер JDBC.
- Операционный контекст персистентности: Hibernate отслеживает состояние текущего объекта через контекст персистентности.
- Запись данных в базу данных: Hibernate записывает данные в базу данных на основе содержимого контекста персистентности.
- Отправьте транзакцию: если транзакция успешно отправлена, Hibernate фактически запишет данные в базу данных.
3.3 Механизм кэширования Hibernate
Механизм кэширования Hibernate может повысить производительность доступа к базе данных. Кэш Hibernate разделен на два уровня: кеш первого уровня и кеш второго уровня.
Кэш первого уровня: Hibernate создает область кэша для каждого запроса пользователя, и все те же объекты кэшируются в этой памяти, чтобы их можно было получить непосредственно из кэша при следующем обращении к ним, вместо повторной загрузки из базы данных.
Кэш второго уровня: Hibernate также поддерживает кеш второго уровня для каждого объектного компонента. Когда объект в кеше изменяется, объект не будет повторно запрашиваться из базы данных при втором обращении к нему, а будет получен непосредственно из кеша, что повышает скорость запроса.
3.4 Декларативное управление транзакциями
Hibernate упрощает процесс обработки данных на уровне бизнес-логики и уровне персистентности посредством механизма декларативного управления транзакциями. Декларативное управление транзакциями реализовано на основе АОП (аспектно-ориентированного программирования).
Декларативное управление транзакциями означает, что нет необходимости явно вызывать функции API транзакций, такие как BeginTransaction() и commit(). Вместо этого аннотации используются непосредственно внутри блока кода транзакции для объявления границ транзакции. Платформа Hibernate автоматически идентифицирует границы транзакций и автоматически полное управление транзакциями.
4. Конкретные примеры кода и подробные пояснения.
4.1 Настройка среды гибернации
4.1.1 Добавление зависимостей Maven
Добавьте следующие зависимости в файл pom.xml проекта:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Optional -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>test</scope>
</dependency>
4.1.2 Создание файла конфигурации Hibernate
Файл конфигурации Hibernate hibernate.cfg.xml выглядит следующим образом:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- SessionFactory settings -->
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/mydatabase?useSSL=false&useUnicode=true&characterEncoding=UTF-8</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (optional) -->
<!--<property name="pool.size">1</property>-->
<!--<property name="pool.max_wait">30000</property>-->
<!--<property name="pool.preferredTestQuery">SELECT 1</property>-->
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Logging -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- Mapping information -->
<mapping resource="com/example/domain/Customer.hbm.xml"/>
<mapping resource="com/example/domain/Order.hbm.xml"/>
</session-factory>
</hibernate-configuration>
connection.*
: Настройте параметры подключения к базе данных.dialect
: Установить диалект базы данных.show_sql
: установите, отображать ли операторы SQL.format_sql
: укажите, форматировать ли выходной оператор SQL.<mapping>
: Настройте файл сопоставления классов сущностей.
4.1.3 Настройка файла сопоставления классов объектов
Пример файла сопоставления классов сущностей:
com/example/domain/Customer.hbm.xml:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example.domain">
<class name="com.example.domain.Customer" table="customers">
<id name="id" type="int">
<generator class="native"/>
</id>
<property name="name" type="string"/>
</class>
</hibernate-mapping>
com/example/domain/Order.hbm.xml:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.example.domain">
<class name="com.example.domain.Order" table="orders">
<id name="orderId" type="int">
<generator class="native"/>
</id>
<property name="date" type="timestamp"/>
<many-to-one name="customer" column="customer_id" class="com.example.domain.Customer"/>
</class>
</hibernate-mapping>
<class>
: Определить класс сущности.<id>
: Определите первичный ключ.<property>
: определение общих атрибутов.<many-to-one>
: Определить ассоциацию «один ко многим».
4.2 Добавление, удаление, изменение и проверка
4.2.1 Вставка данных
import org.hibernate.*;
import com.example.domain.Customer;
...
try{
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
try{
// create a new customer object
Customer customer = new Customer();
customer.setName("John Smith");
// persist the customer object
session.save(customer);
tx.commit();
}catch (HibernateException e){
if (tx!= null){
tx.rollback();
}
throw e;
}finally{
session.close();
}
}catch (HibernateException e){
e.printStackTrace();
}
- Получить сеанс через SessionFactory.
- Выполните операцию вставки в транзакцию и зафиксируйте транзакцию.
- Если возникает исключение, транзакция откатывается.
4.2.2 Удаление данных
import org.hibernate.*;
import com.example.domain.Customer;
...
try{
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
try{
// delete an existing customer object
Integer custId =...;
Customer customer = (Customer) session.load(Customer.class, custId);
session.delete(customer);
tx.commit();
}catch (HibernateException e){
if (tx!= null){
tx.rollback();
}
throw e;
}finally{
session.close();
}
}catch (HibernateException e){
e.printStackTrace();
}
- Получить сеанс через SessionFactory.
- Выполните операцию удаления в транзакции и зафиксируйте транзакцию.
- Если возникает исключение, транзакция откатывается.
4.2.3 Обновление данных
import org.hibernate.*;
import com.example.domain.Customer;
...
try{
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
try{
// update an existing customer object
Integer custId =...;
Customer customer = (Customer) session.load(Customer.class, custId);
customer.setName("Mary Johnson");
session.update(customer);
tx.commit();
}catch (HibernateException e){
if (tx!= null){
tx.rollback();
}
throw e;
}finally{
session.close();
}
}catch (HibernateException e){
e.printStackTrace();
}
- Получить сеанс через SessionFactory.
- Выполните операции обновления в транзакции и зафиксируйте транзакцию.
- Если возникает исключение, транзакция откатывается.
4.2.4 Запрос данных
import org.hibernate.*;
import com.example.domain.Customer;
import java.util.List;
...
try{
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
try{
// retrieve all customers
List results = session.createQuery("from Customer").list();
for (Object result : results){
System.out.println(((Customer)result).getName());
}
tx.commit();
}catch (HibernateException e){
if (tx!= null){
tx.rollback();
}
throw e;
}finally{
session.close();
}
}catch (HibernateException e){
e.printStackTrace();
}
- Получить сеанс через SessionFactory.
- Выполните операции запроса в транзакции и зафиксируйте транзакцию.
- Получите список результатов запроса.
- Если возникает исключение, транзакция откатывается.
4.3 Пейджинговый запрос
Синтаксис SQL-запроса подкачки следующий:
SELECT * FROM Customers LIMIT?,?;
?
Заполнители используются для представления параметров и для передачи параметров подкачки.
В Hibernate вы можете использовать методы firstResult()
и maxResults()
для установки параметров подкачки, как показано ниже:
List results = session.createQuery("from Customer")
.setFirstResult((page - 1) * pageSize)
.setMaxResults(pageSize)
.list();
Здесь (page - 1) * pageSize
представлено количество пропущенных записей, pageSize
указывающее количество записей на странице.
5. Будущие тенденции и проблемы развития
Платформа ORM постоянно обновляется и совершенствуется. С ростом популярности веб-приложений требования становятся все более и более сложными.Традиционная модель разработки, основанная на операторах SQL, постепенно упраздняется, и постепенно появляются новые модели распределенной, высокой доступности и эластично масштабируемой архитектуры. В то же время люди уделяют все больше внимания управлению жизненным циклом программного обеспечения, а микросервисная архитектура становится основной тенденцией, что также стимулирует обновление и модернизацию различных инфраструктур ORM.
Каковы основные направления будущего фреймворка ORM?
Spring Data: это платформа ORM, продвигаемая командой платформы Spring IO. Spring Data — это уровень абстракции, основанный на Spring FrameWork, обеспечивающий унифицированный интерфейс доступа к данным поверх платформы ORM. Его преимущество состоит в том, что он обеспечивает более объектно-ориентированный способ доступа к данным и снижает затраты на обучение программистов. Кроме того, Spring Data также предоставляет различные репозитории, позволяющие пользователям настраивать операции доступа к данным.
Mybatis: MyBatis — это проект с открытым исходным кодом, созданный Apache Foundation и обеспечивающий реализацию платформы ORM. MyBatis хорошо работает с другими платформами ORM на Java, такими как Hibernate.
EclipseLink: EclipseLink — это реализация JPA с открытым исходным кодом, управляемая Eclipse Foundation. EclipseLink добавляет множество функций в дополнение к спецификации JPA, включая встроенное кэширование, асинхронные запросы, изоляцию арендаторов и т. д. Более того, EclipseLink также имеет относительно большие преимущества в производительности.
TopLink: TopLink — очень старая платформа ORM, которая когда-то была приобретена Sun. Среди них OpenJPA — версия TopLink с открытым исходным кодом. Однако в последние годы OpenJPA был приобретен Oracle, поэтому теперь все больше используют Hibernate.