以下是使用 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. 核心步骤
-
启用生成键返回:
在prepareStatement()
中传入Statement.RETURN_GENERATED_KEYS
,告知 JDBC 需要返回生成的键。 -
执行插入并获取键:
executeUpdate()
执行插入操作。getGeneratedKeys()
返回包含生成键的ResultSet
。
-
处理结果集:
generatedKeys.next()
移动到第一条记录(假设每次插入一条)。getLong(1)
获取第一列(主键列)的值。
2. 数据库表结构(MySQL 示例)
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY, -- 自增主键
name VARCHAR(50),
email VARCHAR(100)
);
关键注意事项
-
数据库支持:
- MySQL:使用
AUTO_INCREMENT
主键。 - Oracle:需指定
RETURNING
子句或使用序列(代码需调整)。 - PostgreSQL:支持
RETURNING
子句,但需调整 SQL 语法。
- MySQL:使用
-
多行插入:
如果插入多行,getGeneratedKeys()
返回所有生成的键,需遍历ResultSet
。 -
列索引:
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);
// 处理每个生成的键
}
}
最佳实践
- 始终使用
try-with-resources
:确保资源自动关闭。 - 验证返回结果:检查
ResultSet
是否有数据,避免空指针异常。 - 数据库兼容性测试:根据实际数据库调整 SQL 语法(如 Oracle 的序列)。
通过此示例,你可以轻松实现插入数据并获取自动生成的主键,适用于大多数关系型数据库!