<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-jdbc-client</artifactId>
<version>5.1.10</version>
</dependency>
Vert.x JDBC 异步客户端 (vertx-jdbc-client)
Vert.x JDBC 客户端允许应用程序通过统一的 Vert.x 响应式异步 API 与任何兼容标准 JDBC 规范的关系型数据库进行无缝交互。
该客户端的对外统一 API 抽象由 SqlClient 接口定义。
要在项目中使用该组件,请在构建描述文件中添加以下依赖:
-
Maven(在
pom.xml中):
-
Gradle(在
build.gradle文件中):
compile 'io.vertx:vertx-jdbc-client:5.1.10'
统一的 SqlClient API 体系
SqlClient 是 Vert.x 官方设计的用于与 SQL 关系型数据库进行通信的响应式异步 API。针对 MySQL、PostgreSQL、SQL Server 与 IBM DB2 等主流数据库,官方均提供了原生的纯异步网络驱动。然而,业界仍有许多关系型数据库缺乏专用纯异步驱动,Vert.x JDBC 客户端正是通过对底层 JDBC 驱动进行非阻塞 Worker 线程封装,对外暴露完全一致的 SqlClient API,让开发者在异构数据库间无缝平滑切换。
创建数据库连接池
一切始于连接池(Pool):
JDBCConnectOptions connectOptions = new JDBCConnectOptions()
.setJdbcUrl("jdbc:h2:~/test")
.setUser("sa")
.setPassword("");
PoolOptions poolOptions = new PoolOptions()
.setMaxSize(16);
Pool pool = JDBCPool.pool(vertx, connectOptions, poolOptions);
连接池的双重操作模式
连接池支持两种运行模式:
-
全托管连接模式(Managed Connection Mode):直接向 Pool 发起查询,连接的获取、语句执行与归还由底层全自动完成,无须担心连接泄漏。
-
手动连接模式(Manual Connection Mode):显式从 Pool 中获取 Connection 对象,适用于需要确保语句执行时序、会话隔离或手动控制事务的场景。
全托管连接模式示例:
pool
.query("SELECT * FROM user")
.execute()
.onFailure(Throwable::printStackTrace)
.onSuccess(rows -> {
for (Row row : rows) {
System.out.println(row.getString("FIRST_NAME"));
}
});
// 预编译语句方式:
pool
.preparedQuery("SELECT * FROM user WHERE emp_id > ?")
.execute(Tuple.of(1000))
.onSuccess(rows -> {
for (Row row : rows) {
System.out.println(row.getString("FIRST_NAME"));
}
});
手动连接模式示例(注意务必归还连接):
pool
.getConnection()
.compose(conn -> conn
.query("SELECT * FROM user")
.execute()
// 极其重要:务必在操作终止后归还连接!
.eventually(conn::close))
.onSuccess(rows -> {
for (Row row : rows) {
System.out.println(row.getString("FIRST_NAME"));
}
});
获取自增主键 (Generated Keys)
在执行批量或单条插入后,可以通过特殊属性 JDBCPool.GENERATED_KEYS_LIST 提取由数据库自动生成的自增主键列表:
String sql = "INSERT INTO insert_table (FNAME, LNAME) VALUES (?, ?)";
List<Tuple> batch = Arrays.asList(
Tuple.of("dave", "developer"),
Tuple.of("eve", "engineer")
);
pool
.preparedQuery(sql)
.executeBatch(batch)
.onSuccess(rows -> {
// 生成的主键列表作为附加行集合返回:
List<Row> lastInsertIds = rows.property(JDBCPool.GENERATED_KEYS_LIST).rows();
List<Long> newIds = lastInsertIds.stream()
.map(r -> r.getLong(0)).collect(Collectors.toList());
});
调用存储过程与数据库函数
传统的 JDBC 调用存储过程需要使用 CallableStatement。Vert.x JDBC 客户端对其进行了优雅的响应式适配,支持通过 SqlOutParam 显式标记输入输出参数:
String sql = "{call customer_lastname(?, ?)}";
pool
.preparedQuery(sql)
.execute(Tuple.of("John", SqlOutParam.OUT(JDBCType.VARCHAR)))
.onSuccess(rows -> {
if (rows.property(JDBCPool.OUTPUT)) {
for (Row row : rows) {
System.out.println(row.getString(0));
}
}
});