Einführung in HikariCP

1. Übersicht

In diesem Einführungsartikel erfahren Sie mehr über das HikariCP JDBC-Verbindungspoolprojekt. Dies ist ein sehr leichtes (mit ca. 130 KB) und blitzschnelles JDBC-Verbindungspooling-Framework, das von Brett Wooldridge um 2012 entwickelt wurde.

2. Einführung

Es gibt mehr Benchmark - Ergebnisse zur Verfügung , die Leistung von HikariCP mit anderem Connection - Pooling - Frameworks vergleichen wie c3p0 , dbcp2 , tomcat und vibur . Zum Beispiel hat das HikariCP-Team unter den Benchmarks veröffentlicht (Originalergebnisse hier verfügbar):

Das Framework ist so schnell, weil die folgenden Techniken angewendet wurden:

  • Engineering auf Bytecode-Ebene - Es wurde ein Engineering auf extremer Bytecode-Ebene (einschließlich nativer Codierung auf Assembly-Ebene) durchgeführt
  • Mikrooptimierungen - obwohl kaum messbar, steigern diese Optimierungen zusammen die Gesamtleistung
  • Intelligente Verwendung des Collections-Frameworks - Die ArrayList wurde durch eine benutzerdefinierte FastList- Klasse ersetzt , die die Bereichsprüfung eliminiert und Entfernungsscans vom Schwanz bis zum Kopf durchführt

3. Maven-Abhängigkeit

Lassen Sie uns eine Beispielanwendung erstellen, um deren Verwendung hervorzuheben. HikariCP bietet Unterstützung für alle Hauptversionen von JVM. Jede Version erfordert ihre Abhängigkeit; Für Java 8 bis 11 haben wir:

 com.zaxxer HikariCP 3.4.5 

Ältere JDK-Versionen wie 6 und 7 werden ebenfalls unterstützt. Die entsprechenden Versionen finden Sie hier und hier. Außerdem können wir die neuesten Versionen im Central Maven Repository überprüfen.

4. Verwendung

Lassen Sie uns nun eine Demo-Anwendung erstellen. Bitte beachten Sie, dass wir eine geeignete JDBC-Treiberklassenabhängigkeit in die pom.xml aufnehmen müssen . Wenn keine Abhängigkeiten angegeben sind, löst die Anwendung eine ClassNotFoundException aus .

4.1. Erstellen einer DataSource

Wir werden die DataSource von HikariCP verwenden , um eine einzelne Instanz einer Datenquelle für unsere Anwendung zu erstellen:

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

Hier ist die Initialisierung im statischen Block zu beachten .

HikariConfig ist die Konfigurationsklasse, mit der eine Datenquelle initialisiert wird. Es enthält vier bekannte Parameter , die unbedingt verwendet werden müssen: Benutzername , Kennwort , jdbcUrl , dataSourceClassName .

Von jdbcUrl und dataSourceClassName soll jeweils einer verwendet werden. Wenn Sie diese Eigenschaft jedoch mit älteren Treibern verwenden, müssen Sie möglicherweise beide Eigenschaften festlegen.

Zusätzlich zu diesen Eigenschaften stehen mehrere andere Eigenschaften zur Verfügung, die möglicherweise nicht alle von anderen Pooling-Frameworks angeboten werden:

  • autoCommit
  • Verbindungszeitüberschreitung
  • idleTimeout
  • maxLifetime
  • connectionTestQuery
  • connectionInitSql
  • validationTimeout
  • MaximumPoolSize
  • poolName
  • allowPoolSuspension
  • schreibgeschützt
  • transactionIsolation
  • leakDetectionThreshold

HikariCP zeichnet sich durch diese Datenbankeigenschaften aus. Es ist weit genug fortgeschritten, um sogar Verbindungslecks selbst zu erkennen!

Eine ausführliche Beschreibung dieser Eigenschaften finden Sie hier.

Wir können HikariConfig auch mit einer Eigenschaftendatei initialisieren, die sich im Ressourcenverzeichnis befindet :

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

Die Eigenschaftendatei sollte ungefähr so ​​aussehen:

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

Wir können auch die auf java.util.Properties basierende Konfiguration verwenden:

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

Alternativ können wir eine Datenquelle direkt initialisieren:

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

4.2. Verwenden einer Datenquelle

Nachdem wir die Datenquelle definiert haben, können wir sie verwenden, um eine Verbindung aus dem konfigurierten Verbindungspool abzurufen und JDBC-bezogene Aktionen auszuführen.

Angenommen, wir haben zwei Tabellen mit den Namen dept und emp , um einen Anwendungsfall für die Mitarbeiterabteilung zu simulieren. Wir werden eine Klasse schreiben, um diese Details mit HikariCP aus der Datenbank abzurufen.

Nachfolgend listen wir die SQL-Anweisungen auf, die zum Erstellen der Beispieldaten erforderlich sind:

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

Bitte beachten Sie, dass bei Verwendung einer speicherinternen Datenbank wie H2 das Datenbankskript automatisch geladen werden muss, bevor der eigentliche Code zum Abrufen der Daten ausgeführt wird. Zum Glück enthält H2 einen INIT- Parameter, mit dem das Datenbankskript zur Laufzeit aus dem Klassenpfad geladen werden kann. Die JDBC-URL sollte folgendermaßen aussehen:

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

Wir müssen eine Methode erstellen, um diese Daten aus der Datenbank abzurufen:

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

Jetzt müssen wir eine JUnit-Methode erstellen, um sie zu testen. Da wir die Anzahl der Zeilen in der Tabelle emp kennen , können wir erwarten, dass die Größe der zurückgegebenen Liste der Anzahl der Zeilen entspricht:

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

5. Schlussfolgerung

In diesem kurzen Tutorial haben wir die Vorteile der Verwendung von HikariCP und seiner Konfiguration kennengelernt.

Wie immer ist der vollständige Quellcode auf GitHub verfügbar.