Spring JdbcClient
最后修改日期:2025 年 6 月 6 日
本教程演示如何使用 Spring 的新 JdbcClient 进行数据库访问。
JdbcClient 是 Spring Framework 6.1 中引入的一个新的流畅 API。 它简化了 JDBC 操作,同时保持了灵活性。 它提供了一种比 JdbcTemplate 更现代的替代方案,并具有更直观的 API。
我们将在所有示例中使用 H2 内存数据库。 JdbcClient 适用于任何符合 JDBC 的数据库。
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.2.7</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
</dependency>
</dependencies>
添加以下依赖项以将 Spring JdbcClient 与 H2 数据库一起使用。
基本 CRUD 操作
此示例演示了基本的创建、读取、更新和删除操作。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.List;
record User(String name, String email) {}
void main() {
DataSource dataSource = new DriverManagerDataSource(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1", "sa", "");
JdbcClient jdbClient = JdbcClient.create(dataSource);
// Create table
jdbClient.sql("""
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
)
""").update();
// Insert data
jdbClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", "Alice")
.param("email", "alice@example.com")
.update();
jdbClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", "Paul")
.param("email", "paul@example.com")
.update();
// Fetch data
List<User> users = jdbClient.sql("SELECT name, email FROM users")
.query(User.class)
.list();
users.forEach(System.out::println);
}
该示例创建了一个表,插入了记录,然后查询它们。
DataSource dataSource = new DriverManagerDataSource(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1", "sa", "");
我们创建了一个 H2 内存数据源。 DB_CLOSE_DELAY=-1 在连接关闭后将数据库保留在内存中。
JdbcClient jdbClient = JdbcClient.create(dataSource);
使用数据源创建 JdbcClient 实例。 JdbcClient 是线程安全的。
jdbClient.sql("CREATE TABLE...").update();
执行 DDL 语句以创建表。 update() 方法执行 SQL。
jdbClient.sql("INSERT...").param("name", "Alice")...update();
使用命名参数插入数据。 参数被安全地绑定以防止 SQL 注入。
List<User> users = jdbClient.sql("SELECT...").query(User.class).list();
查询记录并将它们映射到 User 记录。 JdbcClient 自动将列名映射到记录组件。
查询单个记录
此示例演示了查询带有可选结果的单个记录。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.Optional;
record User(String name, String email) {}
void main() {
DataSource dataSource = new DriverManagerDataSource(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1", "sa", "");
JdbcClient jdbcClient = JdbcClient.create(dataSource);
// Create table
jdbcClient.sql("""
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
)
""").update();
// Insert data
jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", "Alice")
.param("email", "alice@example.com")
.update();
// Fetch single record by ID
Optional<User> user = jdbcClient.sql("SELECT name, email FROM users WHERE id = :id")
.param("id", 1L)
.query(User.class)
.optional();
user.ifPresent(System.out::println);
}
该示例查询一个包含在 Optional 中的单个用户记录。
Optional<User> user = jdbcClient.sql("SELECT...").param("id", 1L)
.query(User.class).optional();
在查询可能不存在的单个记录时使用 optional()。 如果未找到结果,它将返回 Optional.empty()。
user.ifPresent(System.out::println);
我们安全地处理 Optional 结果。 仅当存在记录时才打印该记录。
将 ParamSource 与 Records 一起使用
此示例演示了如何将 records 用作参数源。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.List;
record User(Long id, String name, String email) {}
void main() {
DataSource dataSource = new DriverManagerDataSource(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1", "sa", "");
JdbcClient jdbcClient = JdbcClient.create(dataSource);
// Create table
jdbcClient.sql("""
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
)
""").update();
// Insert using paramSource with a record
User newUser = new User(null, "Mark", "mark@example.com");
int updated = jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.paramSource(newUser)
.update();
System.out.println("Rows updated: " + updated);
// Fetch data
List<User> users = jdbcClient.sql("SELECT * FROM users")
.query(User.class)
.list();
users.forEach(System.out::println);
}
该示例演示了使用 record 作为参数源。
User newUser = new User(null, "Mark", "mark@example.com");
创建一个新的 User record。 id 为 null,因为它将自动生成。
jdbcClient.sql("INSERT...").paramSource(newUser).update();
使用 paramSource 将 record 属性绑定到 SQL 参数。 属性名称必须与参数名称匹配。
List<User> users = jdbcClient.sql("SELECT * FROM users")
.query(User.class)
.list();
查询所有用户并映射到 User 记录。 id 列自动映射到记录组件。
计数记录
此示例演示了如何执行标量查询,如 count。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
record User(String name, String email) {}
void main() {
DataSource dataSource = new DriverManagerDataSource(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1", "sa", "");
JdbcClient jdbcClient = JdbcClient.create(dataSource);
// Create table
jdbcClient.sql("""
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
)
""").update();
// Insert data
jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", "Alice")
.param("email", "alice@example.com")
.update();
jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", "Paul")
.param("email", "paul@example.com")
.update();
// Count records
Integer count = jdbcClient.sql("SELECT COUNT(*) FROM users")
.query(Integer.class)
.single();
System.out.println("Total users: " + count);
}
该示例统计 users 表中的记录。
Integer count = jdbcClient.sql("SELECT COUNT(*) FROM users")
.query(Integer.class)
.single();
对于标量查询,指定返回类型并使用 single。 它期望只有一行,一列。
System.out.println("Total users: " + count);
打印计数结果。 该查询返回表中的行数。
高级查询
此示例演示了更高级的查询技术。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
record User(Long id, String name, String email) {}
void main() {
DataSource dataSource = new DriverManagerDataSource(
"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1", "sa", "");
JdbcClient jdbcClient = JdbcClient.create(dataSource);
// Create table
jdbcClient.sql("""
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
)
""").update();
// Insert sample data
List.of(
new User(null, "Alice", "alice@example.com"),
new User(null, "Bob", "bob@example.com"),
new User(null, "Charlie", "charlie@example.com")
).forEach(user -> {
jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.paramSource(user)
.update();
});
// Query with filtering and sorting
List<User> filteredUsers = jdbcClient.sql("""
SELECT id, name, email FROM users
WHERE name LIKE :pattern
ORDER BY name DESC
""")
.param("pattern", "A%")
.query(User.class)
.list();
System.out.println("Filtered users:");
filteredUsers.forEach(System.out::println);
// Query to Map
List<Map<String, Object>> usersAsMaps = jdbcClient.sql("SELECT * FROM users")
.query()
.listOfRows();
System.out.println("\nUsers as maps:");
usersAsMaps.forEach(System.out::println);
}
该示例显示了过滤查询和映射到不同的结果类型。
List<User> filteredUsers = jdbcClient.sql("SELECT...WHERE name LIKE :pattern")
.param("pattern", "A%")
.query(User.class)
.list();
使用带有命名参数的 SQL WHERE 子句过滤记录。 该查询仅返回名称以“A”开头的用户。
List<Map<String, Object>> usersAsMaps = jdbcClient.sql("SELECT * FROM users")
.query()
.listOfRows();
当未指定特定映射时,查询可以将结果作为 Map 返回。 每行都成为列名到值的 Map。
usersAsMaps.forEach(System.out::println);
打印每行的 map 表示形式。 用于调试或在事先不知道结构时很有用。
来源
在本教程中,我们探讨了 Spring 的 JdbcClient 以进行数据库访问。 它为常见的 JDBC 操作提供了一个现代的、流畅的 API。
作者
列出所有Java教程。