51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

JdbcTemplate 获取自增ID

JdbcTemplate 是由 spring-jdbc 提供的一个 JDBC 工具类模块,可以快速地对数据库进行 CURD 操作。

本文将会教你如何在使用 JdbcTemplate 执行 INSERT 操作时获取到自增ID。

项目设置 {#项目设置}

创建任意 spring boot 项目。添加 mysql-connector-j 以及 spring-boot-starter-jdbc 依赖。 你可以通过 start.springboot.io 快速创建此示例项目。

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
</dependency>

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>

配置数据源 {#配置数据源}

application.yaml 中配置基础的数据源信息。

spring:
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    username: root
    password: root

配置 JdbcTemplate {#配置-jdbctemplate}

通过配置类,注册 JdbcTemplate Bean。

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate;

@Configuration public class JdbcTemplateConfiguration {

@Bean
public JdbcTemplate jdbcTemplate (DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}

}

创建示例表 {#创建示例表}

CREATE TABLE `users` (
  `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `account` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账户',
  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统用户';

其中 id 字段是自增的。

GeneratedKeyHolder {#generatedkeyholder}

spring-jdbc 提供了一个 GeneratedKeyHolder 类,通过它可以获取到自增列的值。

public class GeneratedKeyHolder implements KeyHolder {
// 返回唯一自增 key 的值
public Number getKey();
// 返回唯一自增 key 的值,指定其返回类型
public &lt;T&gt; T getKeyAs(Class&lt;T&gt; keyType);

// 返回多个自增 key 及其值
public Map&lt;String, Object&gt; getKeys();
public List&lt;Map&lt;String, Object&gt;&gt; getKeyList();

}

JdbcTeplate 获取自增 ID {#jdbcteplate-获取自增-id}

src/test/main 包下创建测试类:

import java.sql.Types;
import java.time.LocalDateTime;
import java.util.Arrays;

import org.junit.Test; import org.junit.runner.RunWith; 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.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.PreparedStatementCreatorFactory; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.test.context.junit4.SpringRunner;

import cn.springdoc.demo.DemoApplication;

@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) public class DemoApplicationTest {

static final Logger logger = LoggerFactory.getLogger(DemoApplicationTest.class);

@Autowired
private JdbcTemplate jdbcTemplate;

@Test
public void test() {

    // 创建 GeneratedKeyHolder 对象
    GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();

    // Insert SQL
    String sql = &quot;INSERT INTO `users`(`id`, `account`, `create_at`, `name`) VALUES(?, ?, ?, ?);&quot;;

    // 初始化 CreatorFactory,指定要执行的 SQL,以及参数的 Jdbc 类型
    PreparedStatementCreatorFactory factory = new PreparedStatementCreatorFactory(sql, 
            Types.BIGINT, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR);
    
    // 需要返回自增记录值
    factory.setReturnGeneratedKeys(true);

    // 设置占位符参数,返回 creator
    PreparedStatementCreator creator = factory
            .newPreparedStatementCreator(Arrays.asList(null, &quot;springdoc.cn&quot;, LocalDateTime.now(), &quot;Spring 中文网&quot;));

    // 执行更新,返回受影响行数
    int retVal = this.jdbcTemplate.update(creator, keyHolder);

    // 通过 keyHolder 获取到自增值
    Long id = keyHolder.getKey().longValue();

    logger.info(&quot;受影响行数 = {}, 自增ID = {}&quot;, retVal, id);
}

}

执行测试,输出日志如下:

INFO 5372 --- [           main] cn.springdoc.test.DemoApplicationTest    : 受影响行数 = 1, 自增ID = 101

NamedParameterJdbcTemplate 获取自增 ID {#namedparameterjdbctemplate-获取自增-id}

NamedParameterJdbcTemplate 封装了 JdbcTeplate,提供了 "命名参数" 的支持。

同样,需要先在配置类中注册 Bean。

@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate (DataSource dataSource) {
    return new NamedParameterJdbcTemplate(dataSource);
}

创建测试:

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test; import org.junit.runner.RunWith; 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.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.test.context.junit4.SpringRunner;

import cn.springdoc.demo.DemoApplication;

@RunWith(SpringRunner.class) @SpringBootTest(classes = DemoApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) public class DemoApplicationTest {

static final Logger logger = LoggerFactory.getLogger(DemoApplicationTest.class);

@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

@Test
public void test() {

    // 创建 GeneratedKeyHolder 对象
    GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();

    // Insert SQL
    String sql = &quot;INSERT INTO `users`(`id`, `account`, `create_at`, `name`) VALUES(:id, :account, :create_at, :name);&quot;;

    // 使用 Map 封装参数,key 就是 SQL 中对应的参数名称
    Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
    params.put(&quot;id&quot;, null);
    params.put(&quot;account&quot;, &quot;springdoc.cn&quot;);
    params.put(&quot;create_at&quot;, LocalDateTime.now());
    params.put(&quot;name&quot;, &quot;Spring 中文网&quot;);
    
    // 执行更新,返回受影响行数
    int retVal = this.namedParameterJdbcTemplate.update(sql, new MapSqlParameterSource(params), keyHolder);
    
    // 通过 keyHolder 获取到自增值
    Long id = keyHolder.getKey().longValue();

    logger.info(&quot;受影响行数 = {}, 自增ID = {}&quot;, retVal, id);
}

}

注意,这里的 insert SQL 语句中,我们使用了 "命名参数" 占位符,而不是问号。

执行测试,输出日志如下:

INFO 13016 --- [           main] cn.springdoc.test.DemoApplicationTest    : 受影响行数 = 1, 自增ID = 102
赞(5)
未经允许不得转载:工具盒子 » JdbcTemplate 获取自增ID