Когда мы настраиваем связь с базой данных в Hibernate, мы подкладываем под приложение мину замедленного действия. Дело в том, что как и в случае в JDBC, Hibernate открывает ровно одно соединение с базой данных и разрешает только одному объекту Session использовать его. Это прекрасно работает в тестовых примерах, где только одно соединение и требуется. Это будет работать в однопоточных программах, которые не смогут использовать больше одной Session в единицу времени, но это приведёт к проблемам в реальном многопоточном приложении. В самом деле, если у вас web приложение, то скорее всего в нём будет несколько нитей, которые обслуживают запросы. Если речь идёт о ETL приложении, то наверняка данные, над которыми оно работает, будут разделены на блоки, которые будут перерабатывать несколько параллельных потоков. Даже настольные приложения сейчас имеют несколько потоков. А соединение то у нас с базой одно. И это проблема.
К счастью решение этой проблемы известно: пулы соединений с базой и Hibernate их отлично поддерживает. Я возьму пример управления сущностями в Hibernate и добавлю к нему два пула соединений. К сожалению поддержка DBCP в Hibernate не очень работоспособна и я не могу рекомендовать её использовать.
HikariCP
Hibernate имеет встроенную поддержку HikariCP. Достаточно лишь указать HikariCP в качестве источника соединений и настроить сам HikariCP. Начать, конечно, нужно с включения HikariCP в сборку:
1
2
3
4
5
6
7
8
9
10
11
|
<properties>
<hikaricp.version>2.4.3</hikaricp.version>
</properties>
<dependencies>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>
</dependencies>
|
Подключение HikariCP и настройка его параметров осуществляется в файле конфигурации Hibernate:
1
2
3
4
5
6
7
8
9
10
11
|
<hibernate-configuration>
<session-factory>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.connection.provider_class">com.zaxxer.hikari.hibernate.HikariConnectionProvider</property>
<property name="hibernate.hikari.dataSourceClassName">org.h2.jdbcx.JdbcDataSource</property>
<property name="hibernate.hikari.dataSource.url">jdbc:h2:mem:test</property>
<mapping class="ru.easyjava.data.hibernate.entity.Operation"/>
</session-factory>
</hibernate-configuration>
|
Опция hibernate.connection.provider_class явно включает в Hibernate поддержку HikariCP. Опции начинающиеся на hibernate.hikari.* передаются непосредственно в HikariCP и настраивают его.
c3p0
Hibernate имеет встроенную первоклассную поддержку c3p0. Достаточно лишь положить необходимые библиотеки в classpath и задать любую опцию c3p0. Необходимых библиотек две: сам c3p0 и библиотека поддержки от hibernate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<properties>
<c3p0.version>0.9.5.2</c3p0.version>
<hibernate.version>5.2.1.Final</hibernate.version>
</properties>
<dependencies>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${hibernate.version}</version>
</dependency>
</dependencies>
|
Hibernate настраивается как обычно, параметры c3p0 передаются с префиксом hibernate.c3p0
1
2
3
4
5
6
7
8
9
10
|
<hibernate-configuration>
<session-factory>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.connection.url">jdbc:h2:mem:test</property>
<property name="hibernate.c3p0.min_size">5</property>
<mapping class="ru.easyjava.data.hibernate.entity.Operation"/>
</session-factory>
</hibernate-configuration>
|
Hibernate не анализирует содержимое параметров с префиксом hibernate.c3p0, но требует наличия по меньшей мере одного такого параметра для автоматического включения пула c3p0.
Код примера доступен на github.