You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何获取SQ_ASONE_TASK_DETAIL_ID.NEXTVAL生成的插入ID?

问题描述

执行INSERT语句时,TASK_SID字段由Oracle序列SQ_ASONE_TASK_DETAIL_ID.NEXTVAL自动生成,调用executeUpdate()完成插入后,需要获取这个生成的ID用于后续查询,但尝试用executeQuery()获取的方式失败。

插入数据的Java代码

l_objPreparedStatement.setString(1, p_sEmailId);
String entrydate = p_mapAsOneEntryDTO.get(i).getEntryForDate();
String projectName = p_mapAsOneEntryDTO.get(i).getProjectName();
String taskNo = p_mapAsOneEntryDTO.get(i).getTaskNo();
String storyNo = p_mapAsOneEntryDTO.get(i).getStoryNo();
String storyTitle = p_mapAsOneEntryDTO.get(i).getStoryTitle();
String comment = p_mapAsOneEntryDTO.get(i).getComments();
String iterationNo = p_mapAsOneEntryDTO.get(i).getIterationNo();
float hrs = Float.parseFloat(p_mapAsOneEntryDTO.get(i).getWorkHours());
String subpro = p_mapAsOneEntryDTO.get(i).getSubProjectcat();
l_objPreparedStatement.setString(2, entrydate);
l_objPreparedStatement.setString(3, projectName);
l_objPreparedStatement.setString(4, taskNo);
l_objPreparedStatement.setString(5, storyNo);
l_objPreparedStatement.setString(6, storyTitle);
l_objPreparedStatement.setString(7, comment);
l_objPreparedStatement.setString(8, iterationNo);
l_objPreparedStatement.setFloat(9, hrs);
l_objPreparedStatement.setString(10, p_sLoggedUser);
l_objPreparedStatement.setString(11, p_sLoggedUser);
l_objPreparedStatement.setString(12, subpro);

l_objPreparedStatement.executeUpdate();

对应的INSERT SQL语句

"INSERT INTO ASONE_TASK_DETAIL (TASK_SID,EMAIL_ID,ENTRY_FOR_DATE,PROJECT_NAME,TASK_NO,STORY_NO,STORY_TITLE,COMMENTS, "
                + "ITERATION_NO,WORK_HOURS,TIMESTAMP,TRIGGER_TYPE,CREATED_BY, "
                + "CREATED_DATE,MODIFIED_BY,MODIFIED_DATE,CATEGORY)VALUES(SQ_ASONE_TASK_DETAIL_ID.NEXTVAL,?,?,?,?,?,?,?,?,?,SYSDATE,'M',?,SYSDATE,?,SYSDATE,?) ";

失败的ID获取代码

ResultSet resultSet = l_objPreparedStatement.executeQuery();
String taskId = String.valueOf(resultSet.getInt("TASK_SID"));
p_mapAsOneEntryDTO.get(i).setID(taskId);

解决方案

针对Oracle数据库,推荐以下几种可靠的方式获取插入时生成的序列值:

方法一:使用INSERT ... RETURNING子句

修改INSERT语句,添加RETURNING TASK_SID INTO ?,通过PreparedStatement注册输出参数获取生成的ID。

修改后的SQL语句

"INSERT INTO ASONE_TASK_DETAIL (TASK_SID,EMAIL_ID,ENTRY_FOR_DATE,PROJECT_NAME,TASK_NO,STORY_NO,STORY_TITLE,COMMENTS, "
+ "ITERATION_NO,WORK_HOURS,TIMESTAMP,TRIGGER_TYPE,CREATED_BY, "
+ "CREATED_DATE,MODIFIED_BY,MODIFIED_DATE,CATEGORY)VALUES(SQ_ASONE_TASK_DETAIL_ID.NEXTVAL,?,?,?,?,?,?,?,?,?,SYSDATE,'M',?,SYSDATE,?,SYSDATE,?) "
+ "RETURNING TASK_SID INTO ?";

调整后的Java代码

// 注册输出参数,类型需匹配TASK_SID的实际字段类型,这里假设为INTEGER
l_objPreparedStatement.registerOutParameter(13, java.sql.Types.INTEGER);

// 执行插入操作
l_objPreparedStatement.executeUpdate();

// 获取生成的TASK_SID
int taskId = l_objPreparedStatement.getInt(13);
p_mapAsOneEntryDTO.get(i).setID(String.valueOf(taskId));

方法二:预获取序列值再插入

先查询序列的下一个值并保存,再将该值作为TASK_SID插入表中,后续直接使用预存的值即可。

步骤1:获取序列值

PreparedStatement seqStmt = connection.prepareStatement("SELECT SQ_ASONE_TASK_DETAIL_ID.NEXTVAL FROM DUAL");
ResultSet rs = seqStmt.executeQuery();
int taskId = 0;
if(rs.next()){
    taskId = rs.getInt(1);
}
seqStmt.close();
rs.close();

步骤2:修改INSERT语句

"INSERT INTO ASONE_TASK_DETAIL (TASK_SID,EMAIL_ID,ENTRY_FOR_DATE,PROJECT_NAME,TASK_NO,STORY_NO,STORY_TITLE,COMMENTS, "
+ "ITERATION_NO,WORK_HOURS,TIMESTAMP,TRIGGER_TYPE,CREATED_BY, "
+ "CREATED_DATE,MODIFIED_BY,MODIFIED_DATE,CATEGORY)VALUES(?,?,?,?,?,?,?,?,?,?,SYSDATE,'M',?,SYSDATE,?,SYSDATE,?) ";

步骤3:设置参数并执行插入

// 将预获取的taskId作为第一个参数传入
l_objPreparedStatement.setInt(1, taskId);
// 其余参数索引依次后移一位
l_objPreparedStatement.setString(2, p_sEmailId);
// ... 其他参数设置保持原有逻辑
l_objPreparedStatement.executeUpdate();

// 直接使用预获取的taskId
p_mapAsOneEntryDTO.get(i).setID(String.valueOf(taskId));

方法三:使用getGeneratedKeys(需驱动支持)

若使用的Oracle JDBC驱动版本支持,可在创建PreparedStatement时指定返回生成的键,再通过getGeneratedKeys()获取ID。

调整后的代码

// 创建PreparedStatement时指定返回TASK_SID字段
PreparedStatement l_objPreparedStatement = connection.prepareStatement(sql, new String[]{"TASK_SID"});

// ... 设置所有参数,执行插入
l_objPreparedStatement.executeUpdate();

// 获取生成的ID
ResultSet rs = l_objPreparedStatement.getGeneratedKeys();
if(rs.next()){
    int taskId = rs.getInt(1);
    p_mapAsOneEntryDTO.get(i).setID(String.valueOf(taskId));
}
rs.close();

注意:该方法依赖JDBC驱动的兼容性,部分旧版本Oracle驱动可能支持不佳,优先推荐前两种方法。


内容的提问来源于stack exchange,提问作者dhS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:45:41