Когда мы настраиваем связь с базой данных в Hibernate, мы подкладываем под приложение мину замедленного действия. Дело в том, что как и в случае в JDBC, Hibernate открывает ровно одно соединение с базой данных и разрешает только одному объекту Session использовать его. Это прекрасно работает в тестовых примерах, где только одно соединение и требуется. Это будет работать в однопоточных программах, которые не смогут использовать больше одной Session в единицу времени, но это приведёт к проблемам в реальном многопоточном приложении. В самом деле, если у вас web приложение, то скорее всего в нём будет несколько нитей, которые обслуживают запросы. Если речь идёт о ETL приложении, то наверняка данные, над которыми оно работает, будут разделены на блоки, которые будут перерабатывать несколько параллельных потоков. Даже настольные приложения сейчас имеют несколько потоков. А соединение то у нас с базой одно. И это проблема.
К счастью решение этой проблемы известно: пулы соединений с базой и Hibernate их отлично поддерживает. Я возьму пример управления сущностями в Hibernate и добавлю к нему два пула соединений. К сожалению поддержка DBCP в Hibernate не очень работоспособна и я не могу рекомендовать её использовать.
HikariCP
Hibernate имеет встроенную поддержку HikariCP. Достаточно лишь указать HikariCP в качестве источника соединений и настроить сам HikariCP. Начать, конечно, нужно с включения HikariCP в сборку:
<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:
<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.
<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
<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.