Автор оригинала: Pankaj Kumar.
Пул соединений означает пул объектов подключения. Объединение пулов соединений основано на шаблоне проектирования пула объектов. Шаблон проектирования объединения объектов используется, когда затраты (время и ресурсы, такие как процессор, сеть и ввод-вывод) на создание новых объектов выше. В соответствии с шаблоном проектирования объединения объектов приложение заранее создает объект и помещает его в пул или контейнер. Всякий раз, когда нашему приложению требуются такие объекты, оно получает их из пула, а не создает новый.
Приложение, использующее стратегию объединения соединений, уже имеет объекты подключения к БД, которые можно использовать повторно. Таким образом, когда возникает необходимость взаимодействия с базой данных, приложение получает экземпляры соединений из пула. Объединение пулов соединений повышает производительность приложений, взаимодействующих с базой данных.
Мы можем создать ваши собственные реализации объединения соединений. Любая структура пула соединений должна выполнять три задачи.
- Создание Объектов Подключения
- Управляйте использованием созданных объектов и проверяйте их
- Освобождайте/Уничтожайте Объекты
С Java у нас есть отличный набор библиотек, которые легко доступны. Нам нужно настроить только несколько свойств, чтобы использовать их.
Объединение пулов соединений в Java-приложении
Давайте взглянем на нижеприведенные библиотеки:
- Apache Commons DBCP2
- ХикариКП
- C3P0
Давайте рассмотрим приведенные ниже примеры из них один за другим. Для демонстрационных целей мы будем использовать базу данных MySQL и среду разработки Eclipse. Мы также создадим простой Java-проект на основе maven с использованием JDK 1.8.
Сценарии базы данных
create database empdb; use empdb; create table tblemployee( empId integer AUTO_INCREMENT primary key, empName varchar(64), dob date, designation varchar(64) ); insert into tblemployee(empId,empName,dob,designation) values (default,'Adam','1998-08-15','Manager'); insert into tblemployee(empId,empName,dob,designation) values (default,'Smith','2001-01-11','Clerk'); insert into tblemployee(empId,empName,dob,designation) values (default,'James','1996-03-13','Officer');
Пример Проекта
Выполните следующие действия, чтобы создать новый проект.
1) Откройте среду разработки Eclipse.
2) Нажмите меню Файл и выберите создать -> Проект Maven
3) Отобразится экран ниже. Выберите опцию создать простой проект и нажмите кнопку Далее.
4) Введите любой идентификатор группы, идентификатор артефакта, Имя и описание.
Нажмите Кнопку Готово.
5) Добавьте следующую зависимость в свой pom.xml для MySQL.
mysql mysql-connector-java 5.1.49
6) Щелкните правой кнопкой мыши на проекте, выберите Maven -> Обновить проект -> Ок. Он загрузит все зависимости.
1) Apache commons DBCP2
DBCP – это общий проект Apache. Для DBCP 2.7 требуется Java 8. Чтобы использовать DBCP 2, вам необходимо добавить в свой проект следующую зависимость.
org.apache.commons commons-dbcp2 2.7.0
Apache DBCP 2.0 предоставляет два типа источников данных (BasicDataSource и PoolingDataSource).
BasicDataSource: Как следует из названия, он прост и подходит для большинства распространенных случаев использования. Это внутренне создает для нас PoolingDataSource.
Давайте рассмотрим приведенные ниже шаги по инициализации пула соединений.
- Создайте экземпляр BasicDataSource
- Укажите URL-адрес JDBC, имя пользователя и пароль базы данных
- Укажите минимальное количество неработающих подключений ( минимальное количество подключений, которое должно оставаться в пуле в любое время).
- Укажите максимальное количество неработающих подключений (Максимальное количество неработающих подключений в пуле).
- Укажите общее максимальное количество подключений.
package com.journaldev.example; /** * Java JDBC Connection pool using Apache commons DBCP2 example program * * @author pankaj */ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.apache.commons.dbcp2.BasicDataSource; public class DBCP2Demo { private static BasicDataSource dataSource = null; static { dataSource = new BasicDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/empdb?useSSL=false"); dataSource.setUsername("root"); dataSource.setPassword("root"); dataSource.setMinIdle(5); dataSource.setMaxIdle(10); dataSource.setMaxTotal(25); } public static void main(String[] args) throws SQLException { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery("select * from tblemployee"); while (resultSet.next()) { System.out.println("empId:" + resultSet.getInt("empId")); System.out.println("empName:" + resultSet.getString("empName")); System.out.println("dob:" + resultSet.getDate("dob")); System.out.println("designation:" + resultSet.getString("designation")); } } finally { resultSet.close(); statement.close(); connection.close(); } } }
Выход:
empId:1 empName:Adam dob:1998-08-15 designation:Manager empId:2 empName:Smith dob:2001-01-11 designation:Clerk empId:3 empName:James dob:1996-03-13 designation:Officer
PoolingDataSource: Он обеспечивает большую гибкость. Вам нужно только изменить код, который создает источник данных. Остальная часть кода останется прежней.
Давайте рассмотрим следующие шаги для инициализации пула соединений:
- Создайте экземпляр ConnectionFactory, используя URL-адрес JDBC.
- Создайте экземпляр PoolableConnectionFactory, используя экземпляр ConnectionFactory, который был создан на шаге 1
- Создайте экземпляр GenericObjectPoolConfig и задайте свойства максимального простоя, минимального простоя и максимального подключения
- Теперь инициализируйте пул объектов, используя экземпляры, созданные на шаге 2 и шаге 3
- Теперь установите пул в качестве экземпляра PoolableConnectionFactory
- Наконец, инициализируйте экземпляр источника данных
private static DataSource dataSource = null; static { Properties properties = new Properties(); properties.setProperty("user", "root"); properties.setProperty("password", "root"); ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://localhost:3306/empdb", properties); PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null); GenericObjectPoolConfigconfig = new GenericObjectPoolConfig<>(); config.setMaxTotal(25); config.setMaxIdle(10); config.setMinIdle(5); ObjectPool connectionPool = new GenericObjectPool<>(poolableConnectionFactory, config); poolableConnectionFactory.setPool(connectionPool); dataSource = new PoolingDataSource<>(connectionPool); }
2) ХикариКП
HikariCP быстр, надежен и прост. Это одно из предпочтительных решений для объединения соединений в пул. Фреймворки, такие как Spring Boot 2.x, используют его в качестве диспетчера соединений по умолчанию.
Чтобы использовать HikariCP, добавьте следующую зависимость в pom.xml вашего проекта.
com.zaxxer HikariCP 3.4.5
Конфигурация HikariCP :
Мы можем использовать конфигурацию на основе Java, как показано в приведенном ниже примере программы, или мы можем использовать файл свойств для настройки HikariCP. Давайте взглянем на приведенные ниже свойства.
- время ожидания простоя : Время в миллисекундах, в течение которого объект подключения может оставаться в пуле в режиме ожидания. Он работает с минимальным временем простоя и Максимальным размером пула свойствами. По истечении указанного времени объект подключения будет освобожден.
- время ожидания подключения : Время в миллисекундах, в течение которого клиент будет ждать объект подключения из пула. Если ограничение по времени будет достигнуто, то будет выдано исключение SQLException.
- autoCommit : Мы можем указать значение true или false, и если оно равно true, то оно автоматически фиксирует все выполняемые вами операторы SQL, а если оно равно false, то нам нужно фиксировать операторы SQL вручную
- cachePrepStmts: Включить кэширование для инструкции Prepare
- минимальное время простоя: Минимальное количество объектов подключения должно оставаться в пуле в любое время.
- Максимальный размер пула : Максимальное количество подключений, которые могут оставаться в пуле.
package com.journaldev.example; /** * Java JDBC Connection pool using HikariCP example program * * @author pankaj */ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; public class HikariCPDemo { private static HikariDataSource dataSource = null; static { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/empdb"); config.setUsername("root"); config.setPassword("root"); config.addDataSourceProperty("minimumIdle", "5"); config.addDataSourceProperty("maximumPoolSize", "25"); dataSource = new HikariDataSource(config); } public static void main(String[] args) throws SQLException { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = dataSource.getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery("select * from tblemployee"); while (resultSet.next()) { System.out.println("empId:" + resultSet.getInt("empId")); System.out.println("empName:" + resultSet.getString("empName")); System.out.println("dob:" + resultSet.getDate("dob")); System.out.println("designation:" + resultSet.getString("designation")); } } finally { resultSet.close(); statement.close(); connection.close(); } } }
Выход:
empId:1 empName:Adam dob:1998-08-15 designation:Manager empId:2 empName:Smith dob:2001-01-11 designation:Clerk empId:3 empName:James dob:1996-03-13 designation:Officer
3) C3P0
C3P0-одна из старейших библиотек. Как правило, он используется с Hibernate. Чтобы использовать C3P0, нам нужно добавить в проект следующую зависимость.
com.mchange c3p0 0.9.5.5
Мы можем настроить следующие свойства с помощью C3P0.
- класс драйвера : Предпочтительный Драйвер Jdbc
- jdbcUrl : Url-адрес JDBC для базы данных.
- Размер начального пула: количество подключений, созданных в пуле при запуске.
- Приобретение: необходимо создать количество новых подключений, если текущего размера недостаточно.
- Максимальное время : Количество секунд, в течение которых соединение может оставаться в пуле без использования.
- maxPoolSize : Максимальное количество подключений, которые могут оставаться в пуле.
- минимальный размер пула: Минимальное количество объектов подключения должно оставаться в пуле в любое время.
package com.journaldev.example; /** * Java JDBC Connection pool using C3PO example program * * @author pankaj */ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Demo { static ComboPooledDataSource comboPooledDataSource = null; static { comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/empdb?useSSL=false"); comboPooledDataSource.setUser("root"); comboPooledDataSource.setPassword("root"); comboPooledDataSource.setMinPoolSize(3); comboPooledDataSource.setAcquireIncrement(3); comboPooledDataSource.setMaxPoolSize(30); } public static void main(String[] args) throws SQLException { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = comboPooledDataSource.getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery("select * from tblemployee"); while (resultSet.next()) { System.out.println("empId:" + resultSet.getInt("empId")); System.out.println("empName:" + resultSet.getString("empName")); System.out.println("dob:" + resultSet.getDate("dob")); System.out.println("designation:" + resultSet.getString("designation")); } } finally { resultSet.close(); statement.close(); connection.close(); } } }
Выход:
Aug 29, 2020 8:59:05 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge9kqacgbp7hjpftse6|77a567e1, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> null, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge9kqacgbp7hjpftse6|77a567e1, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/empdb?useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 30, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] empId:1 empName:Adam dob:1998-08-15 designation:Manager empId:2 empName:Smith dob:2001-01-11 designation:Clerk empId:3 empName:James dob:1996-03-13 designation:Officer
Это все для примера руководства по пулу соединений JDBC, я надеюсь, что здесь не было пропущено ничего важного.
Ссылки : HikariCP , Apache Commons DBCP , C3P0