java 的 preparedstatement 没有直接设置 rowid 参数的方法,因为 jdbc 规范中不存在针对 rowid 的专用 setter。要使用 rowid,必须通过 setobject(int parameterindex, object x) 方法传入一个实现了 java.sql.rowid 接口的对象。通常这个对象由 resultset.getrowid() 获取,或者通过 connection.createrowid(long length) 创建。调用 setobject 后,驱动程序会将该对象转换为数据库特定的 rowid 类型进行绑定。

如何从 ResultSet 获取并传递 RowId
最常见的场景是从查询结果中获取某行的 RowId,然后将其作为参数传递给另一个更新或删除语句。你需要先执行查询获取包含 RowId 的 ResultSet,调用 getRowId(columnLabel) 拿到 RowId 实例,接着准备目标 SQL 语句并使用 setObject 进行绑定。这种方式确保了行标识符在不同 SQL 上下文中的正确传递。

import java.sql.*;
public class RowIdExample {
public static void main(String[] args) throws Exception {
// 假设已建立连接 conn
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "user", "pass");
// 1. 获取 RowId
String querySql = "SELECT rowid, emp_name FROM employees WHERE emp_id = ?";
PreparedStatement psGet = conn.prepareStatement(querySql);
psSet.setInt(1, 101);
ResultSet rs = psGet.executeQuery();
RowId rid = null;
if (rs.next()) {
rid = rs.getRowId("rowid");
}
rs.close();
psGet.close();
if (rid != null) {
// 2. 使用 RowId 进行更新
String updateSql = "UPDATE employees SET status = ? WHERE rowid = ?";
PreparedStatement psUpdate = conn.prepareStatement(updateSql);
psUpdate.setString(1, "ACTIVE");
psUpdate.setObject(2, rid); // 关键步骤:使用 setObject
int rowsAffected = psUpdate.executeUpdate();
System.out.println("Updated rows: " + rowsAffected);
psUpdate.close();
}
conn.close();
}
}上述代码在 Oracle 数据库中运行。第一步查询返回的 RowId 对象包含了物理行地址。第二步将 rid 传给 setObject,驱动将其映射为 Oracle 的 ROWID 类型。如果数据库不支持 RowId(如 MySQL),此操作会抛出 SQLException。预期结果是 employees 表中 ID 为 101 的行状态被更新为 ACTIVE,且 rowsAffected 为 1。
立即学习“Java免费学习笔记(深入)”;
如何动态创建 RowId 对象用于插入
在某些高级场景中,可能需要手动构造 RowId 对象,例如在批量处理或特定数据迁移逻辑中。可以通过 Connection.createRowId(int length) 创建一个指定长度的空 RowId 对象,然后使用其 setBytes 方法填充具体的字节数据。这种方法允许开发者完全控制 RowId 的二进制表示,但需要确保字节数组符合底层数据库的 ROWID 格式要求。

import java.sql.*;
public class CreateRowIdExample {
public static void main(String[] args) throws Exception {
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "user", "pass");
// 1. 创建 RowId 对象
RowId newRid = conn.createRowId(10);
// 2. 填充字节数据 (示例数据)
byte[] data = new byte[10];
for (int i = 0; i < 10; i++) {
data[i] = (byte) i;
}
newRid.setBytes(0, data);
// 3. 使用自定义 RowId 插入
String insertSql = "INSERT INTO audit_log (log_id, log_rowid, created_at) VALUES (?, ?, ?)";
PreparedStatement psInsert = conn.prepareStatement(insertSql);
psInsert.setInt(1, 999);
psInsert.setObject(2, newRid); // 绑定自定义 RowId
psInsert.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
int result = psInsert.executeUpdate();
System.out.println("Inserted with custom RowId: " + result);
psInsert.close();
conn.close();
}
}这段代码展示了如何手动构建 RowId。首先调用 createRowId(10) 分配空间,然后通过 setBytes 写入具体值。最后通过 setObject 将其绑定到插入语句。注意,不同数据库对 RowId 长度和格式要求不同,Oracle 通常支持较长长度,而某些数据库可能忽略手动设置的 RowId 或报错。预期输出为 Inserted with custom RowId: 1,表示成功插入一行,且该行带有指定的 RowId 值。
当 RowId 为 null 时 PreparedStatement 的行为
如果在调用 setObject 时传入的 RowId 对象为 null,JDBC 驱动程序会将其视为 SQL NULL 值进行处理。这意味着在 UPDATE 或 DELETE 语句中,WHERE rowid = ? 的条件将匹配不到任何行,因为 NULL 不等于任何值。在 INSERT 语句中,对应的列将被设置为 NULL。这种行为符合 SQL 标准,但在业务逻辑中可能导致意外结果,因此建议在绑定前检查 RowId 是否为 null。


















