Introducción a HikariCP

1. Información general

En este artículo introductorio, aprenderemos sobre el proyecto de grupo de conexiones HikariCP JDBC. Se trata de un marco de agrupación de conexiones JDBC muy ligero (aproximadamente 130 Kb) y ultrarrápido desarrollado por Brett Wooldridge alrededor de 2012.

2. Introducción

Hay varios resultados de referencia disponibles para comparar el rendimiento de HikariCP con otros marcos de agrupación de conexiones como c3p0 , dbcp2 , tomcat y vibur . Por ejemplo, el equipo de HikariCP publicó los siguientes puntos de referencia (los resultados originales están disponibles aquí):

El marco es tan rápido porque se han aplicado las siguientes técnicas:

  • Ingeniería a nivel de bytecode: se ha realizado una ingeniería extrema a nivel de bytecode (incluida la codificación nativa a nivel de ensamblaje)
  • Microoptimizaciones: aunque apenas se pueden medir, estas optimizaciones combinadas aumentan el rendimiento general
  • El uso inteligente del marco Colecciones - el ArrayList fue sustituida por una clase personalizada lista rápida que elimina la comprobación de rango y la eliminación realiza exploraciones desde la cola hasta la cabeza

3. Dependencia de Maven

Creemos una aplicación de muestra para resaltar su uso. HikariCP viene con soporte para todas las versiones principales de JVM. Cada versión requiere su dependencia; para Java 8 a 11, tenemos:

 com.zaxxer HikariCP 3.4.5 

También se admiten versiones anteriores de JDK como 6 y 7. Las versiones apropiadas se pueden encontrar aquí y aquí. Además, podemos consultar las últimas versiones en el Repositorio Central Maven.

4. Uso

Creemos ahora una aplicación de demostración. Tenga en cuenta que debemos incluir una dependencia de clase de controlador JDBC adecuada en pom.xml . Si no se proporcionan dependencias, la aplicación lanzará una ClassNotFoundException .

4.1. Crear una fuente de datos

Usaremos DataSource de HikariCP para crear una instancia única de una fuente de datos para nuestra aplicación:

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(); } }

El punto a tener en cuenta aquí es la inicialización en el bloque estático .

HikariConfig es la clase de configuración utilizada para inicializar una fuente de datos. Viene con cuatro conocidos parámetros de uso obligatorio: nombre de usuario , contraseña , jdbcUrl , dataSourceClassName .

Fuera de jdbcUrl y dataSourceClassName , cualquiera de los dos debe usarse a la vez. Sin embargo, al usar esta propiedad con controladores más antiguos, es posible que necesitemos establecer ambas propiedades.

Además de estas propiedades, hay varias otras propiedades disponibles que pueden no ser todas ofrecidas por otros marcos de agrupación:

  • autoCommit
  • el tiempo de conexión expiro
  • tiempo de inactividad
  • maxLifetime
  • connectionTestQuery
  • connectionInitSql
  • validationTimeout
  • maximumPoolSize
  • poolName
  • allowPoolSuspension
  • solo lectura
  • transactionIsolation
  • fugaDetección Umbral

HikariCP se destaca por estas propiedades de base de datos. ¡Es lo suficientemente avanzado como para detectar incluso fugas de conexión por sí mismo!

Puede encontrar una descripción detallada de estas propiedades aquí.

También podemos inicializar HikariConfig con un archivo de propiedades ubicado en el directorio de recursos :

private static HikariConfig config = new HikariConfig( "datasource.properties" );

El archivo de propiedades debería verse así:

dataSourceClassName= //TBD dataSource.user= //TBD //other properties name should start with dataSource as shown above

También podemos usar la configuración basada en 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 );

Alternativamente, podemos inicializar una fuente de datos directamente:

ds.setJdbcUrl( //TBD ); ds.setUsername( //TBD ); ds.setPassword( //TBD );

4.2. Usando una fuente de datos

Ahora que hemos definido la fuente de datos, podemos usarla para obtener una conexión del grupo de conexiones configurado y realizar acciones relacionadas con JDBC.

Suponga que tenemos dos tablas llamadas dept y emp para simular un caso de uso de empleado-departamento. Escribiremos una clase para obtener esos detalles de la base de datos usando HikariCP.

A continuación, enumeramos las declaraciones SQL necesarias para crear los datos de muestra:

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 );

Tenga en cuenta que si usamos una base de datos en memoria como H2, necesitamos cargar automáticamente el script de la base de datos antes de ejecutar el código real para obtener los datos. Afortunadamente, H2 viene con un parámetro INIT que puede cargar el script de la base de datos desde la ruta de clase en tiempo de ejecución. La URL de JDBC debería verse así:

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;INIT=runscript from 'classpath:/db.sql'

Necesitamos crear un método para obtener estos datos de la base de datos:

public static List fetchData() throws SQLException { String SQL_QUERY = "select * from emp"; List 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; }

Ahora, necesitamos crear un método JUnit para probarlo. Como conocemos el número de filas en la tabla emp , podemos esperar que el tamaño de la lista devuelta sea igual al número de filas:

@Test public void givenConnection_thenFetchDbData() throws SQLException { HikariCPDemo.fetchData(); assertEquals( 4, employees.size() ); }

5. Conclusión

En este tutorial rápido, aprendimos sobre los beneficios de usar HikariCP y su configuración.

Como siempre, el código fuente completo está disponible en GitHub.