Introduction à HikariCP

1. Vue d'ensemble

Dans cet article d'introduction, nous découvrirons le projet de pool de connexions HikariCP JDBC. Il s'agit d'un cadre de regroupement de connexions JDBC très léger (à environ 130 Ko) et ultra-rapide développé par Brett Wooldridge vers 2012.

2. Présentation

Il existe plusieurs résultats de référence disponibles pour comparer les performances de HikariCP avec d'autres frameworks de regroupement de connexions tels que c3p0 , dbcp2 , tomcat et vibur . Par exemple, l'équipe HikariCP a publié ci-dessous les benchmarks (résultats originaux disponibles ici):

Le framework est si rapide car les techniques suivantes ont été appliquées:

  • Ingénierie au niveau du bytecode - une certaine ingénierie extrême au niveau du bytecode (y compris le codage natif au niveau de l'assemblage) a été réalisée
  • Micro-optimisations - bien qu'à peine mesurables, ces optimisations combinées augmentent les performances globales
  • Une utilisation intelligente du cadre Collections - l' ArrayList a été remplacée par une classe personnalisée liste rapide qui élimine et vérifie la plage effectue des scans retrait de la queue à la tête

3. Dépendance de Maven

Construisons un exemple d'application pour mettre en évidence son utilisation. HikariCP prend en charge toutes les versions principales de JVM. Chaque version nécessite sa dépendance; pour Java 8 à 11, nous avons:

 com.zaxxer HikariCP 3.4.5 

Les anciennes versions de JDK comme 6 et 7 sont également prises en charge. Les versions appropriées peuvent être trouvées ici et ici. Nous pouvons également vérifier les dernières versions dans le référentiel central de Maven.

4. Utilisation

Créons maintenant une application de démonstration. Veuillez noter que nous devons inclure une dépendance de classe de pilote JDBC appropriée dans le fichier pom.xml . Si aucune dépendance n'est fournie, l'application lèvera une ClassNotFoundException .

4.1. Créer une DataSource

Nous utiliserons la DataSource de HikariCP pour créer une seule instance d'une source de données pour notre application:

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

Point à noter ici est l'initialisation dans le bloc statique .

HikariConfig est la classe de configuration utilisée pour initialiser une source de données. Il est livré avec quatre paramètres bien connus: nom d'utilisateur , mot de passe , jdbcUrl , dataSourceClassName .

Hors jdbcUrl et dataSourceClassName , l'un ou l'autre doit être utilisé à la fois. Cependant, lors de l'utilisation de cette propriété avec des pilotes plus anciens, il se peut que nous devions définir les deux propriétés.

En plus de ces propriétés, il existe plusieurs autres propriétés disponibles qui peuvent ne pas toutes être proposées par d'autres frameworks de pooling:

  • autoCommit
  • délai de connection dépassé
  • délai d'inactivité
  • maxLifetime
  • connectionTestQuery
  • connectionInitSql
  • validationTimeout
  • maximumPoolSize
  • poolName
  • allowPoolSuspension
  • lecture seulement
  • transactionIsolation
  • fuiteDetectionThreshold

HikariCP se distingue par ces propriétés de base de données. Il est suffisamment avancé pour même détecter les fuites de connexion par lui-même!

Une description détaillée de ces propriétés peut être trouvée ici.

Nous pouvons également initialiser HikariConfig avec un fichier de propriétés placé dans le répertoire des ressources :

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

Le fichier de propriétés devrait ressembler à ceci:

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

Nous pouvons également utiliser la configuration basée sur 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 );

Alternativement, nous pouvons initialiser une source de données directement:

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

4.2. Utilisation d'une source de données

Maintenant que nous avons défini la source de données, nous pouvons l'utiliser pour obtenir une connexion à partir du pool de connexions configuré et effectuer des actions liées à JDBC.

Supposons que nous ayons deux tables nommées dept et emp pour simuler un cas d'utilisation employé-service. Nous écrirons une classe pour récupérer ces détails de la base de données en utilisant HikariCP.

Ci-dessous, nous listons les instructions SQL nécessaires pour créer les exemples de données:

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

Veuillez noter que si nous utilisons une base de données en mémoire telle que H2, nous devons charger automatiquement le script de base de données avant d'exécuter le code réel pour récupérer les données. Heureusement, H2 est livré avec un paramètre INIT qui peut charger le script de base de données à partir du chemin de classe au moment de l'exécution. L'URL JDBC doit ressembler à:

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

Nous devons créer une méthode pour récupérer ces données de la base de données:

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

Maintenant, nous devons créer une méthode JUnit pour la tester. Puisque nous connaissons le nombre de lignes dans la table emp , nous pouvons nous attendre à ce que la taille de la liste retournée soit égale au nombre de lignes:

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

5. Conclusion

Dans ce rapide didacticiel, nous avons découvert les avantages de l'utilisation de HikariCP et de sa configuration.

Comme toujours, le code source complet est disponible à l'adresse over sur GitHub.