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教程。