JdbcClient 返回自增 ID
JdbcClient
是 Spring 6.1 引入的一个 Jdbc 客户端工具类,提供了 Fluent 链式调用风格的查询和更新方法,支持 JDBC 风格的位置参数和 Spring 风格的命名参数绑定。
本文将带你了解,如何在使用 JdbcClient
执行 insert
操作时返回自增 ID。
关于
JdbcClient
更多详细的用法可以参阅 “Spring 6 JdbcClient API 指南” 和 “Spring Boot 中的新 JDBC 客户端: JdbcClient”
创建数据表
在本地 MYSQL 数据库 demo
中创建一张简单的 t_user
表,如下:
CREATE TABLE `t_user` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`enabled` tinyint unsigned NOT NULL COMMENT '是否启用。0:禁用,1:启用',
`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '名字',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户';
其中, id
列是自增列。
Spring Boot 项目设置
创建一个简单的 Spring Boot 应用,添加 spring-boot-starter-jdbc
依赖以及 MYSQL 的驱动:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
然后,在 application.yaml
中配置数据源信息:
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&allowMultiQueries=true
username: root
password: root
spring-boot-starter-jdbc
模块会自动使用配置的数据源来创建 JdbcClient
Bean,不需要自己手动实例化。
JdbcClient 获取自增 ID
和 JdbcTemplate
一样, JdbcClient
也通过 KeyHolder
接口来获取到 insert
记录的自增 ID。
package cn.springdoc.demo.test;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class DemoApplicationTests {
static final Logger log = LoggerFactory.getLogger(DemoApplicationTests.class);
@Autowired
JdbcClient jdbcClient;
@Test
public void test() throws Exception {
// 创建 KeyHolder 实现
KeyHolder keyHolder = new GeneratedKeyHolder();
int ret = this.jdbcClient.sql("INSERT INTO `demo`.`t_user` (`id`, `create_at`, `enabled`, `name`) VALUES (:id, :create_at, :enabled, :name);")
.param("id", null) // 自增列的值设置为 null
.param("create_at", LocalDateTime.now())
.param("enabled", Boolean.TRUE)
.param("name", "springdoc.cn")
.update(keyHolder) // 执行 insert,传递 KeyHolder 实现
;
// 从 keyHolder 获取到自增ID
long id = keyHolder.getKey().longValue();
log.info("受影响的行数:{}", ret);
log.info("自增的ID:{}", id);
}
}
如上,首先在测试类中注入 spring-data-jdbc
自动配置的 JdbcClient
实例。
然后实例化 KeyHolder
接口的实现 GeneratedKeyHolder
,用于获取自增的 ID。
调用 jdbcClient
的 sql
方法,传递 INSERT
语句,使用命名参数占位符,接着调用 param
方法依次按照参数名称设置参数值。然后调用 update
方法,传递 KeyHolder
实现并执行 INSERT
SQL 语句。
最后返回受影响的行数。插入记录的自增 ID 可以通过 keyHolder
接口的 getKey()
方法获取到。
执行该测试,控制台输出如下:
c.s.demo.test.DemoApplicationTests : 受影响的行数:1
c.s.demo.test.DemoApplicationTests : 自增的ID:1