当前位置: 首页 > news >正文

如何在Spring JDBC 中获取自动生成的 ID

 在此页面上,我们将学习如何在Spring JDBC中获取自动生成的ID。在Spring  JDBC 中,我们可以使用JdbcTemplate方法和SimpleJdbcInsert方法来执行 SQL 查询,并将自动生成的密钥作为KeyHolder返回。

KeyHolder

KeyHolder是用于检索自动生成的密钥的接口。​​​​​​​KeyHolder由 JDBC 插入语句返回。通常,键作为List包含每行键的键的​​​​​​​​​​​​​​Map键返回。
KeyHolder具有以下方法。
getKey() :从第一张地图中检索第一个项目。
getKeyAs(Class<T> keyType)  从给定键类型的第一个映射中检索第一个项目。
getKeyList()  :返回对包含密钥的列表的引用。
getKeys() :检索第一个密钥映射。​​​​​​​


 

使用 Jdbc 模板更新

从春季文档中查找方法声明。JdbcTemplate.update

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder) throws DataAccessException 

1. 该方法使用PreparedStatementCreator发出更新语句。
2.生成的密钥将被放入给定的KeyHolder.
3. 该方法返回受影响的行数。

示例 :​​​​​​​

String sql = "insert into person (name, age) values (?, ?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
			PreparedStatement pst = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
			pst.setString(1, p.getName());
			pst.setInt(2, p.getAge());
			return pst;
		}, keyHolder);
int id = keyHolder.getKey().intValue(); 

使用简单Jdbc插入

SimpleJdbcInsert为工作台提供简单的插入功能。我们需要提供的只是表的名称和包含列名和列值的​​​​​​​Map。查找执行SimpleJdbcInsert查询并返回自动生成的密钥的方法。​​​​​​​

Number executeAndReturnKey(Map<String,?> args)
Number executeAndReturnKey(SqlParameterSource parameterSource)
KeyHolder executeAndReturnKeyHolder(Map<String,?> args)
KeyHolder executeAndReturnKeyHolder(SqlParameterSource parameterSource) 

示例
在这里,我们使用JdbcTemplate.update和​​​​​​​KeyHolder检索自动生成的密钥。

Map<String, Object> params = new HashMap<String, Object>();
params.put("name", p.getName());
params.put("age", p.getAge());

KeyHolder keyHolder = simpleJdbcInsert
	.withTableName("person")
	.usingColumns("name", "age")
	.usingGeneratedKeyColumns("id")
	.withoutTableColumnMetaDataAccess()	    
	.executeAndReturnKeyHolder(params);
int id = keyHolder.getKey().intValue(); 

完整示例

表:person

CREATE TABLE `person` (
	`id` INT(5) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(100) NOT NULL,
	`age` INT(3) NOT NULL,
	PRIMARY KEY (`id`)
) 

PersonDAO.java

package com.concretepage;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

@Repository
public class PersonDAO {
  @Autowired
  private JdbcTemplate jdbcTemplate;
  
  private SimpleJdbcInsert simpleJdbcInsert;
  
  @Autowired
  private void setSimpleJdbcInsert(JdbcTemplate jdbcTemplate) {
	simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
  }
  
  public void addPersonUsingJdbcTemplate(Person p) {
	String sql = "insert into person (name, age) values (?, ?)";
	KeyHolder keyHolder = new GeneratedKeyHolder();
	jdbcTemplate.update(connection -> {
	            PreparedStatement pst = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
	            pst.setString(1, p.getName());
	            pst.setInt(2, p.getAge());
	            return pst;
	        }, keyHolder);
	int id = keyHolder.getKey().intValue();
	p.setId(id);
	System.out.println(id);
  }
  
  public void addPersonUsingSimpleJdbcInsert(Person p) {
	Map<String, Object> params = new HashMap<String, Object>();
	params.put("name", p.getName());
	params.put("age", p.getAge());
	
	KeyHolder keyHolder = simpleJdbcInsert
	    .withTableName("person")
	    .usingColumns("name", "age")
	    .usingGeneratedKeyColumns("id")
	    .withoutTableColumnMetaDataAccess()	    
	    .executeAndReturnKeyHolder(params);
	int id = keyHolder.getKey().intValue();
	p.setId(id);
	System.out.println(id);
  }  
} 

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/concretepage
spring.datasource.username=root
spring.datasource.password=cp
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 

Person.java

package com.concretepage;
public class Person {
    private int id;
	private String name;
	private int age;
	public Person(String name, int age) {
	  this.name = name;
	  this.age = age;
	}
	public int getId() {
	  return id;
	}
	public void setId(int id) {
	  this.id = id;
	}
	public String getName() {
	  return name;
	}
	public int getAge() {
	  return age;
	}
	@Override
	public String toString() {
	  return id + " - " + name + " - " + age;
	}
} 

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.concretepage</groupId>
    <artifactId>soap-ws</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>spring-demo</name>
    <description>Spring Demo Application</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath />
    </parent>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

MyApplication.java

package com.concretepage;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class MyApplication {
  public static void main(String[] args) {
	ApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
	PersonDAO personDAO = ctx.getBean(PersonDAO.class);
	
	Person p1 = new Person("Mohan", 25);
	personDAO.addPersonUsingJdbcTemplate(p1);
	System.out.println(p1);
	Person p2 = new Person("Shiva", 30);
	personDAO.addPersonUsingSimpleJdbcInsert(p2);
	System.out.println(p2);
  }
}

引用

Interface KeyHolder
Class JdbcTemplate
Class SimpleJdbcInsert

下载源代码

how-to-get-auto-generated-id-in-spring-jdbc.zip

相关文章:

  • C语言—《动态版通讯录》
  • JSP+Servlet + Tomcat实现用户登录(五)使用listener实现在线(游客)人数统计【JavaWeb、无数据库】
  • 【SpringBoot】抽取公共页面方法
  • 应急响应(个人总结,非专业
  • memcpy内存比较函数;memset内存设置函数
  • 【0基础学习mysql】之DQL-聚合函数、分组查询及排序查询
  • 【Redis】回顾下Redis基础知识点,还记得哪些?
  • redis五种数据类型内部构造
  • 基于Vue+Element UI+SSM+SpringCloud的员工管理系统
  • LeetCode刷题---二分查找巩固
  • 简单概述理解vue的MVVM模型
  • 24、Java——银行存款取款系统(对象+集合)
  • Python 集合
  • 【DS】5.二叉树大总结!
  • 攻防世界 web2
  • Android 架构优化~MVP 架构改造
  • cookie和session
  • ES2017异步函数现已正式可用
  • Java 网络编程(2):UDP 的使用
  • JavaScript 奇技淫巧
  • java第三方包学习之lombok
  • LintCode 31. partitionArray 数组划分
  • 测试开发系类之接口自动化测试
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 观察者模式实现非直接耦合
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于HAProxy的高性能缓存服务器nuster
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 设计模式走一遍---观察者模式
  • 使用agvtool更改app version/build
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 详解移动APP与web APP的区别
  • !$boo在php中什么意思,php前戏
  • #define
  • (16)Reactor的测试——响应式Spring的道法术器
  • (8)STL算法之替换
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (八十八)VFL语言初步 - 实现布局
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (十六)Flask之蓝图
  • (十五)使用Nexus创建Maven私服
  • .bat文件调用java类的main方法
  • .chm格式文件如何阅读
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net 获取url的方法
  • .NET 指南:抽象化实现的基类
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .net下简单快捷的数值高低位切换
  • .net专家(高海东的专栏)
  • @ConditionalOnProperty注解使用说明
  • @test注解_Spring 自定义注解你了解过吗?