使用 JDBC 插入数据并获取自动生成的主键(如 MySQL 的 AUTO_INCREMENT 或 Oracle 的序列) 的完整示例代码,包含详细注释

news2025/3/22 21:10:03

以下是使用 JDBC 插入数据并获取自动生成的主键(如 MySQL 的 AUTO_INCREMENT 或 Oracle 的序列) 的完整示例代码,包含详细注释:


import java.sql.*;

public class GeneratedKeysExample {
    // 数据库连接参数
    private static final String URL = "jdbc:mysql://localhost:3306/mydatabase";
    private static final String USER = "root";
    private static final String PASSWORD = "your_password";

    public static void main(String[] args) {
        Connection conn = null;
        try {
            // 1. 加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. 获取数据库连接
            conn = DriverManager.getConnection(URL, USER, PASSWORD);

            // 3. 定义插入语句(包含自增主键)
            String sql = "INSERT INTO users (name, email) VALUES (?, ?)";

            // 4. 创建 PreparedStatement 并启用返回生成的键
            try (PreparedStatement pstmt = conn.prepareStatement(
                    sql, 
                    Statement.RETURN_GENERATED_KEYS // 关键:启用生成键的返回
            )) {

                // 5. 设置参数
                pstmt.setString(1, "Alice");
                pstmt.setString(2, "alice@example.com");

                // 6. 执行插入操作
                int affectedRows = pstmt.executeUpdate();
                System.out.println("插入成功,影响行数:" + affectedRows);

                // 7. 获取生成的主键
                try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
                    if (generatedKeys.next()) {
                        long userId = generatedKeys.getLong(1); // 获取第一列(主键)
                        System.out.println("生成的用户ID:" + userId);
                    } else {
                        throw new SQLException("创建用户时未获取到主键!");
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            System.out.println("JDBC驱动未找到!");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("数据库操作失败!");
            e.printStackTrace();
        } finally {
            // 8. 关闭连接
            try {
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

代码说明

1. 核心步骤
  1. 启用生成键返回
    prepareStatement() 中传入 Statement.RETURN_GENERATED_KEYS,告知 JDBC 需要返回生成的键。

  2. 执行插入并获取键

    • executeUpdate() 执行插入操作。
    • getGeneratedKeys() 返回包含生成键的 ResultSet
  3. 处理结果集

    • generatedKeys.next() 移动到第一条记录(假设每次插入一条)。
    • getLong(1) 获取第一列(主键列)的值。

2. 数据库表结构(MySQL 示例)
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY, -- 自增主键
    name VARCHAR(50),
    email VARCHAR(100)
);

关键注意事项

  1. 数据库支持

    • MySQL:使用 AUTO_INCREMENT 主键。
    • Oracle:需指定 RETURNING 子句或使用序列(代码需调整)。
    • PostgreSQL:支持 RETURNING 子句,但需调整 SQL 语法。
  2. 多行插入
    如果插入多行,getGeneratedKeys() 返回所有生成的键,需遍历 ResultSet

  3. 列索引
    generatedKeys.getLong(1) 中的 1 表示主键是结果集的第一列。若表有多个生成列,需根据列顺序调整。


扩展场景:Oracle 示例

Oracle 需要使用 RETURNING 子句和序列:

// Oracle 示例代码片段
String sql = "INSERT INTO users (id, name, email) " +
             "VALUES (user_seq.NEXTVAL, ?, ?) " +
             "RETURNING id INTO ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
    pstmt.setString(1, "Alice");
    pstmt.setString(2, "alice@example.com");
    pstmt.registerOutParameter(3, OracleTypes.NUMBER); // 注册输出参数

    int rows = pstmt.executeUpdate();
    long userId = pstmt.getLong(3); // 通过输出参数获取主键
}

常见问题

Q1:为什么获取不到生成的键?
  • 原因:未在 prepareStatement() 中启用 RETURN_GENERATED_KEYS
  • 解决:确保代码中包含 Statement.RETURN_GENERATED_KEYS
Q2:如何处理批量插入的生成键?
// 批量插入示例
pstmt.addBatch(); // 添加多条数据
pstmt.executeBatch();

// 获取所有生成的键
try (ResultSet keys = pstmt.getGeneratedKeys()) {
    while (keys.next()) {
        long id = keys.getLong(1);
        // 处理每个生成的键
    }
}

最佳实践

  1. 始终使用 try-with-resources:确保资源自动关闭。
  2. 验证返回结果:检查 ResultSet 是否有数据,避免空指针异常。
  3. 数据库兼容性测试:根据实际数据库调整 SQL 语法(如 Oracle 的序列)。

通过此示例,你可以轻松实现插入数据并获取自动生成的主键,适用于大多数关系型数据库!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2319782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图解AUTOSAR_CP_EEPROM_Abstraction

AUTOSAR EEPROM抽象模块详细说明 基于AUTOSAR标准的EEPROM抽象层技术解析 目录 1. 概述 1.1 核心功能1.2 模块地位2. 架构概览 2.1 架构层次2.2 模块交互3. 配置结构 3.1 主要配置容器3.2 关键配置参数4. 状态管理 4.1 基本状态4.2 状态转换5. 接口设计 5.1 主要接口分类5.2 接…

汇川EASY系列之以太网通讯(MODBUS_TCP做从站)

汇川easy系列PLC做MODBUS_TCP从站,不需要任何操作,但是有一些需要知道的东西。具体如下: 1、汇川easy系列PLC做MODBUS_TCP从站,,ModbusTCP服务器默认开启,无需设置通信协议(即不需要配置),端口号为“502”。ModbusTCP从站最多支持31个ModbusTCP客户端(ModbusTCP主站…

QT 图表(拆线图,栏状图,饼状图 ,动态图表)

效果 折线图 // 创建折线数据系列// 创建折线系列QLineSeries *series new QLineSeries;// series->append(0, 6);// series->append(2, 4);// series->append(3, 8);// 创建图表并添加系列QChart *chart new QChart;chart->addSeries(series);chart->setTit…

基于vue框架的在线影院系统a079l(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能:用户,电影,电影类别,电影库 开题报告内容 基于Vue框架的在线影院系统开题报告 一、研究背景与意义 随着文化娱乐产业的蓬勃发展,电影院作为人们休闲消遣的重要场所,其管理效率和服务质量直接影响着顾客的观影体…

OpenCV图像拼接(1)概述

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 此图说明了在Stitcher类中实现的拼接模块流程。使用该类,可以配置/移除某些步骤,即根据特定需求调整拼接流程。流程中的所…

基于ssm学科竞赛小程序的设计及实现(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着信息时代的来临,过去的学科竞赛管理方式的缺点逐渐暴露,本次对过去的学科竞赛管理方式的缺点进行分析,采取计算机方式构建学科竞赛小程序。本文通过阅读相关文献,研究国内外相关技术,提出了一种关于竞赛信息…

[特殊字符][特殊字符][特殊字符][特殊字符][特殊字符][特殊字符]壁紙 流光染墨,碎影入梦

#Cosplay #🧚‍♀️Bangni邦尼🐰. #📷 穹妹 Set.01 #后期圈小程序 琼枝低垂,霜花浸透夜色,风起时,微光轻拂檐角,洒落一地星辉。远山隐于烟岚,唯余一抹青黛,勾勒出天光水…

虚拟机的三种 Linux 网络配置原理图解读

前言 虚拟机的网络连接方式主要有 三种模式:桥接模式(Bridged)、NAT 模式(Network Address Translation)、仅主机模式(Host-Only)。每种模式都有不同的使用场景和网络适应性,具体解释…

AI Agent系列(七) -思维链(Chain of Thought,CoT)

AI Agent系列【七】 前言一、CoT技术详解1.1 CoT组成1.2 CoT的特点 二、CoT的作用三、CoT的好处四、CoT适用场景五、CoT的推理结构 前言 思维链(Chain of Thought,CoT),思维链就是一系列中间的推理步骤(a series of intermediate reasoning steps),通过…

SpringBoot实现异步调用的方法

在Java中使用Spring Boot实现异步请求和异步调用是一个常见的需求,可以提高应用程序的性能和响应能力。以下是实现这两种异步操作的基本方法: 一、异步请求(Asynchronous Request) 异步请求允许客户端发送请求后立即返回&#x…

PurpleLlama大模型安全全套检测方案

1. 引入 PurpleLlama是Meta的大模型安全整体解决方案(参考1),它包括了 (1)安全评估 CyberSecEval是一个用于评估大型语言模型(LLMs)安全风险的基准套件,其目标是解决随着 LLMs 的广…

vue el-table 设置selection选中状态

toggleRowSelection 方法 vue el-table 设置selection选中状态 关键代码 multipleTableRef.value!.toggleRowSelection(item, true);<el-table:data"data":border"setBorder"v-bind"$attrs"row-key"id"stripestyle"width: 1…

STM32学习笔记之常用总线(原理篇)

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

【数据结构】栈(Stack)、队列(Queue)、双端队列(Deque) —— 有码有图有真相

目录 栈和队列 1. 栈&#xff08;Stack&#xff09; 1.1 概念 1.2 栈的使用&#xff08;原始方法&#xff09; 1.3 栈的模拟实现 【小结】 2. 栈的应用场景 1、改变元素的序列 2、将递归转化为循环 3、逆波兰表达式求值 4、括号匹配 5、出栈入栈次序匹配 6、最小栈…

OpenCV中的矩阵操作

OpenCV中的矩阵操作主要围绕Mat类展开&#xff0c;涵盖创建、访问、运算及变换等。 1. 创建矩阵 ‌零矩阵/单位矩阵‌&#xff1a; Mat zeros Mat::zeros(3, 3, CV_32F); // 3x3浮点零矩阵 Mat eye Mat::eye(3, 3, CV_32F); // 3x3单位矩阵 自定义初始化‌&#xff1a…

OAK相机入门(一):深度测距原理

文章目录 1. 测距参数介绍2. 测距原理3. 总结 官方文档 Configuring Stereo Depth 1. 测距参数介绍 理论范围&#xff1a;0.2-35m 推荐范文&#xff1a;不低于0.5m 存储类型&#xff1a;uint16&#xff0c;0代表没有数据&#xff0c;或者测不到 2. 测距原理 通过视差进行测距…

Powershell WSL .wslconfig 实现与宿主机的网络互通

前言.wslconfig .wslconfig 用于在 WSL 2 上运行的所有已安装发行版中配置全局设置 wsl 2 网络模式介绍 Bridged (外部): 桥接模式将虚拟机的网络连接直接桥接到物理网络适配器上Mirrored (镜像): 镜像模式并不是一个标准的 Hyper-V 网络类型,但它通常指的是在网络适配器级…

Vue:Vue2和Vue3创建项目的几种常用方式以及区别

前言 Vue.js 和 Element UI 都是用 JavaScript 编写的。 1、Vue.js 是一个渐进式 JavaScript 框架。2、Element UI 是基于 Vue.js 的组件库。3、JavaScript 是这两个项目的主要编程语言。 而Element Plus是基于TypeScript开发的。 一、Vue2 1、基于vuecli工具创建 vue2 …

IRF拆除

冗余口、冗余组、备份组、虚墙、MAD检测、被控制器纳管、转换为安全策略 黑洞路由的定义: 有来无回的路由。 对设备拆除IRF操作流程。 1、关闭主框的业务口&#xff08;对设备的接口使用shutdown&#xff09;&#xff0c;关闭MAD检测口&#xff08;BFD/NQA/MAD&#xff09;&…

强化学习(赵世钰版)-学习笔记(8.值函数方法)

本章是算法与方法的第四章&#xff0c;是TD算法的拓展&#xff0c;本质上是将状态值与行为值的表征方式&#xff0c;从离散的表格形式&#xff0c;拓展到了连续的函数形式。 表格形式的优点是直观&#xff0c;便于分析&#xff0c;缺点是数据量较大或者连续性状态或者行为空间时…