1. Обзор
В этом вводном руководстве мы узнаем о проекте пула соединений HikariCP JDBC . Это очень легкая (примерно 130 КБ) и молниеносная среда пула соединений JDBC, разработанная Бреттом Вулдриджем примерно в 2012 году.
2. Введение
Доступно несколько тестовых результатов для сравнения производительности HikariCP с другими платформами пула соединений, такими как c3p0
, dbcp2
, tomcat
и vibur
. Например, команда HikariCP опубликовала следующие бенчмарки (исходные результаты доступны здесь ):
Фреймворк такой быстрый, потому что были применены следующие методы:
- Разработка на уровне байт-кода - была выполнена некоторая экстремальная разработка на уровне байт-кода (включая собственное кодирование на уровне сборки).
- Микрооптимизации — хотя их едва можно измерить, в совокупности эти оптимизации повышают общую производительность.
- Интеллектуальное использование платформы коллекций — ArrayList
<Statement>
был заменен настраиваемым классомFastList,
который устраняет проверку диапазона и выполняет сканирование удаления от начала до конца.
3. Зависимость от Maven
Во-первых, давайте создадим пример приложения, чтобы выделить его использование. HikariCP поставляется с поддержкой всех основных версий JVM. Каждая версия требует своей зависимости. Для Java с 8 по 11 у нас есть:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
HikariCP также поддерживает более старые версии JDK, вроде 6 и 7. Соответствующие версии можно найти здесь и здесь соответственно. Мы также можем проверить последние версии в Центральном репозитории Maven .
4. Использование
Теперь мы можем создать демонстрационное приложение. Обратите внимание, что нам нужно включить подходящую зависимость класса драйвера JDBC в pom.xml
. Если зависимости не указаны, приложение выдаст исключение ClassNotFoundException
.
4.1. Создание источника данных
Мы будем использовать HikariCP DataSource
для создания одного экземпляра источника данных для нашего приложения:
public class DataSource {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
config.setJdbcUrl( "jdbc_url" );
config.setUsername( "database_username" );
config.setPassword( "database_password" );
config.addDataSourceProperty( "cachePrepStmts" , "true" );
config.addDataSourceProperty( "prepStmtCacheSize" , "250" );
config.addDataSourceProperty( "prepStmtCacheSqlLimit" , "2048" );
ds = new HikariDataSource( config );
}
private DataSource() {}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
Здесь следует отметить один момент — инициализацию в статическом
блоке.
HikariConfig — это класс конфигурации, используемый для инициализации источника данных. Он поставляется с четырьмя известными обязательными параметрами: имя пользователя
, пароль
, jdbcUrl
и dataSourceClassName
.
Из jdbcUrl
и dataSourceClassName
мы обычно используем по одному. Однако при использовании этого свойства со старыми драйверами нам может потребоваться установить оба свойства.
В дополнение к этим свойствам есть несколько других доступных свойств, которые мы можем не найти в других платформах объединения:
автофиксация
время соединения вышло
idleTimeout
maxLifetime
соединениеTestQuery
соединениеInitSql
валидациятаймаут
максимальный размер пула
имя_пула
allowPoolSuspension
только для чтения
изоляция транзакции
Порог обнаружения утечки
HikariCP выделяется из-за этих свойств базы данных. Он даже достаточно продвинут, чтобы самостоятельно обнаруживать утечки соединений.
Подробное описание вышеуказанных свойств можно найти здесь .
Мы также можем инициализировать HikariConfig
с помощью файла свойств, расположенного в каталоге ресурсов
:
private static HikariConfig config = new HikariConfig(
"datasource.properties" );
Файл свойств должен выглядеть примерно так:
dataSourceClassName= //TBD
dataSource.user= //TBD
//other properties name should start with dataSource as shown above
Кроме того, мы можем использовать конфигурацию на основе java.util.Properties :
Properties props = new Properties();
props.setProperty( "dataSourceClassName" , //TBD );
props.setProperty( "dataSource.user" , //TBD );
//setter for other required properties
private static HikariConfig config = new HikariConfig( props );
В качестве альтернативы мы можем инициализировать источник данных напрямую:
ds.setJdbcUrl( //TBD );
ds.setUsername( //TBD );
ds.setPassword( //TBD );
4.2. Использование источника данных
Теперь, когда мы определили источник данных, мы можем использовать его для получения соединения из настроенного пула соединений и выполнения действий, связанных с JDBC.
Предположим, у нас есть две таблицы с именами dept
и emp
для имитации варианта использования «сотрудник-отдел». Мы напишем класс для извлечения этих деталей из базы данных с помощью HikariCP.
Ниже мы перечислим операторы SQL, необходимые для создания примера данных:
create table dept(
deptno numeric,
dname varchar(14),
loc varchar(13),
constraint pk_dept primary key ( deptno )
);
create table emp(
empno numeric,
ename varchar(10),
job varchar(9),
mgr numeric,
hiredate date,
sal numeric,
comm numeric,
deptno numeric,
constraint pk_emp primary key ( empno ),
constraint fk_deptno foreign key ( deptno ) references dept ( deptno )
);
insert into dept values( 10, 'ACCOUNTING', 'NEW YORK' );
insert into dept values( 20, 'RESEARCH', 'DALLAS' );
insert into dept values( 30, 'SALES', 'CHICAGO' );
insert into dept values( 40, 'OPERATIONS', 'BOSTON' );
insert into emp values(
7839, 'KING', 'PRESIDENT', null,
to_date( '17-11-1981' , 'dd-mm-yyyy' ),
7698, null, 10
);
insert into emp values(
7698, 'BLAKE', 'MANAGER', 7839,
to_date( '1-5-1981' , 'dd-mm-yyyy' ),
7782, null, 20
);
insert into emp values(
7782, 'CLARK', 'MANAGER', 7839,
to_date( '9-6-1981' , 'dd-mm-yyyy' ),
7566, null, 30
);
insert into emp values(
7566, 'JONES', 'MANAGER', 7839,
to_date( '2-4-1981' , 'dd-mm-yyyy' ),
7839, null, 40
);
Обратите внимание: если мы используем базу данных в памяти, такую как H2, нам необходимо автоматически загрузить сценарий базы данных перед запуском фактического кода для извлечения данных. К счастью, H2 поставляется с параметром INIT
, который может загружать скрипт базы данных из пути к классам во время выполнения. URL-адрес JDBC должен выглядеть так:
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;INIT=runscript from 'classpath:/db.sql'
Нам нужно создать метод для извлечения этих данных из базы данных:
public static List<Employee> fetchData() throws SQLException {
String SQL_QUERY = "select * from emp";
List<Employee> employees = null;
try (Connection con = DataSource.getConnection();
PreparedStatement pst = con.prepareStatement( SQL_QUERY );
ResultSet rs = pst.executeQuery();) {
employees = new ArrayList<>();
Employee employee;
while ( rs.next() ) {
employee = new Employee();
employee.setEmpNo( rs.getInt( "empno" ) );
employee.setEname( rs.getString( "ename" ) );
employee.setJob( rs.getString( "job" ) );
employee.setMgr( rs.getInt( "mgr" ) );
employee.setHiredate( rs.getDate( "hiredate" ) );
employee.setSal( rs.getInt( "sal" ) );
employee.setComm( rs.getInt( "comm" ) );
employee.setDeptno( rs.getInt( "deptno" ) );
employees.add( employee );
}
}
return employees;
}
Затем нам нужно создать метод JUnit для его проверки. Поскольку мы знаем количество строк в таблице emp
, мы можем ожидать, что размер возвращаемого списка должен быть равен количеству строк:
@Test
public void givenConnection_thenFetchDbData() throws SQLException {
HikariCPDemo.fetchData();
assertEquals( 4, employees.size() );
}
5. Вывод
В этой краткой статье мы узнали о преимуществах использования HikariCP и его настройке.
Как всегда, полный исходный код доступен на GitHub .