使用 HikariCP 连接池
最后修改于 2020 年 7 月 13 日
在本教程中,我们将介绍 HikariCP,并展示如何在 Java 应用程序中设置 HikariCP 连接池。在我们的应用程序中,我们向 MySQL 数据库发出请求。
HikariCP 是一个稳定、高性能的 JDBC 连接池。 连接池 是一个数据库连接缓存,用于在未来需要访问数据库时重用连接。连接池可以显著降低整体资源使用率。
Java 数据库连接 (JDBC) 是一个用于访问关系数据库的 Java API。它提供了查询和更新数据库中数据的方法。 Spring Boot 是 Spring 的约定优于配置解决方案,用于快速创建独立的、生产级别的 Spring 应用程序。 JdbcTemplate 是一个库,可以帮助程序员创建使用关系数据库和 JDBC 的应用程序。它处理许多繁琐且容易出错的底层细节,例如事务处理、资源清理和正确处理异常。
-- SQL for the Cars table START TRANSACTION; DROP TABLE IF EXISTS Cars; CREATE TABLE Cars(Id INTEGER PRIMARY KEY, Name VARCHAR(50), Price INTEGER); INSERT INTO Cars VALUES(1, 'Audi', 52642); INSERT INTO Cars VALUES(2, 'Mercedes', 57127); INSERT INTO Cars VALUES(3, 'Skoda', 9000); INSERT INTO Cars VALUES(4, 'Volvo', 29000); INSERT INTO Cars VALUES(5, 'Bentley', 350000); INSERT INTO Cars VALUES(6, 'Citroen', 21000); INSERT INTO Cars VALUES(7, 'Hummer', 41400); INSERT INTO Cars VALUES(8, 'Volkswagen', 21600); COMMIT;
在示例中,我们使用此表。
mysql> source cars.sql
可以使用 mysql 命令行工具轻松创建该表。有关如何设置和使用 MySQL 数据库的更多信息,您可以参考 MySQL 教程。
控制台应用程序中的 HikariCP
在以下示例中,我们将 HikariCP 用于 Java 控制台应用程序。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zetcode</groupId>
<artifactId>HikariCPEx</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.22</version>
</dependency>
</dependencies>
<name>HikariCPEx</name>
</project>
在 Maven 构建文件中,我们提供了 MySQL 驱动程序核心、HikariCP 连接池和 slf4j-simple 库的依赖项。(HikariCP 需要 slf4j)。
jdbcUrl=jdbc:mysql://:3306/testdb?useSSL=false dataSource.user=testuser dataSource.password=test623 dataSource.cachePrepStmts=true dataSource.prepStmtCacheSize=250 dataSource.prepStmtCacheSqlLimit=2048
在 db.properties 文件中,我们具有数据源的配置设置。该文件位于 src/main/resources 目录中。
package com.zetcode;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HikariCPEx {
public static void main(String[] args) {
String configFile = "src/main/resources/db.properties";
HikariConfig cfg = new HikariConfig(configFile);
HikariDataSource ds = new HikariDataSource(cfg);
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
con = ds.getConnection();
pst = con.prepareStatement("SELECT * FROM Cars");
rs = pst.executeQuery();
while (rs.next()) {
System.out.format("%d %s %d %n", rs.getInt(1), rs.getString(2),
rs.getInt(3));
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(HikariCPEx.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pst != null) {
pst.close();
}
if (con != null) {
con.close();
}
ds.close();
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(HikariCPEx.class.getName());
lgr.log(Level.WARNING, ex.getMessage(), ex);
}
}
}
}
该示例连接到 MySQL 数据库,并从其 Cars 表中选择所有汽车。
String configFile = "src/main/resources/db.properties"; HikariConfig cfg = new HikariConfig(configFile);
我们使用数据库属性创建 HikariConfig 对象,该对象用于创建数据源。
HikariDataSource ds = new HikariDataSource(cfg);
创建了一个 HikariDataSource。
con = ds.getConnection();
通过数据源,我们使用 getConnection 方法获取连接。
pst = con.prepareStatement("SELECT * FROM Cars");
rs = pst.executeQuery();
我们创建了一个预编译语句(prepared statement),稍后使用 executeQuery 方法执行它。
ds.close();
close 方法会关闭数据源及其关联的连接池。
Spring Boot 应用程序中的 HikariCP
在第二个应用程序中,我们将 HikariCP 用于 Spring Boot 应用程序。该应用程序是一个简单的 Spring Boot 控制台应用程序。
该项目包含六个文件:pom.xml、hikari.properties、Car.java、Application.java、MyRunner.java 和 AppConfig.java。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zetcode</groupId>
<artifactId>SpringBootHikariCP</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
</dependencies>
<name>SpringBootHikariCP</name>
</project>
这是 pom.xml 文件。它包含 Spring Boot、MySQL 驱动程序和 HikariCP 的依赖项。Spring Boot 会自动处理日志依赖项。
package com.zetcode.bean;
public class Car {
private Long Id;
private String name;
private int price;
public Long getId() {
return Id;
}
public void setId(Long Id) {
this.Id = Id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" + "Id=" + Id + ", name=" +
name + ", price=" + price + '}';
}
}
这是一个简单的 Car Bean,它将映射到 Cars 表中的一行。
driverClassName=com.mysql.jdbc.Driver jdbcUrl=jdbc:mysql://:3306/testdb?useSSL=false maximumPoolSize=20 username=testuser password=test623 dataSource.cachePrepStmts=true dataSource.prepStmtCacheSize=250 dataSource.prepStmtCacheSqlLimit=2048
hikari.properties 文件位于 src/main/resources 目录中,包含 HikariCP 的配置选项。
package com.zetcode.conf;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean(destroyMethod = "close")
public DataSource dataSource() throws SQLException {
HikariConfig config = new HikariConfig("/hikari.properties");
HikariDataSource dataSource = new HikariDataSource(config);
return dataSource;
}
}
AppConfig 是一个配置 Bean,用于设置 HikariDataSource。 @Bean 注释表示一个方法会生成一个由 Spring 容器管理的 Bean。
package com.zetcode.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
@EnableAutoConfiguration
@ComponentScan(basePackages="com.zetcode")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application 类构建应用程序。 @EnableAutoConfiguration 注释启用 Spring Boot 自动配置。 @ComponentScan 注释告诉 Spring 在哪里查找要创建的 Bean。
package com.zetcode.client;
import com.zetcode.bean.Car;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyRunner implements CommandLineRunner {
@Autowired
protected JdbcTemplate jtm;
@Override
public void run(String... args) throws Exception {
String sql = "SELECT * FROM Cars";
List<Car> cars = jtm.query(sql, new BeanPropertyRowMapper(Car.class));
cars.stream().forEach(System.out::println);
}
}
在 MyRunner 类中,我们注入 JdbcTemplate 对象并执行其 query 方法。 BeanPropertyRowMapper 将数据库表行映射到 Car Bean。