使用jdbc在oracle中 获得最新插入的主键值?

duanjianbo26 2009-05-14 11:48:53
如题,我是使用触发器和序列自动生成主键。插入一条记录后该如何返回最新插入的主键值呢?
部分代码如下:

public void getlist() throws UnsupportedEncodingException {
Connection con = Connect.getCon();
ResultSet rs = null;
Statement stm = null;
members.clear();
String ctymsql="";
try {

con.setAutoCommit(false);
stm = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
int rows = sh.getRows();
System.out.println(rows);
String email="";
for (int i = 1; i < rows; i++) {

sql.getsql(i);
email=sh.getCell(sql.getCytmembermap().get("EMAIL"), i).getContents();

ctymsql = sql.getCtymsql();
ctyhList.add(sql.getCtyhsql());
//ctymList.add(sql.getCtymsql());
ctysList.add(sql.getCtyssql());
//System.out.println(m6699sql);
stm.executeUpdate(ctymsql, Statement.RETURN_GENERATED_KEYS);
//System.out.println("-------------");


int autoIncKeyFromFunc = -1;
rs = stm.executeQuery("select member_autoinc.currval as cur from dual");
if (rs.next()) {
autoIncKeyFromFunc = rs.getInt("cur");
members.add(autoIncKeyFromFunc);


if(!email.equals("")){
//插入数据表member_email
stm.execute("insert into tbl_member_email(MEMBER_ID,EMAIL,FLAG) value("+autoIncKeyFromFunc+",'"+email+"',0)");
}

} else {
// throw an exception from here
}
rs.close();
rs = null;

}
con.commit();
...全文
1128 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
钱呈 2011-12-22
  • 打赏
  • 举报
回复
1.bao110908 这个是正解。具体确实如他所言需要实现JDBC 3.0 Spec。一共有3种做法。方法1:指定clumnName[] 2.指定clumnIndex[]
2.根据oracle的标准currValue这个之前必须要先执行nextValue。这两个调用必须在同一次事务(更正确的讲可能是session)中。否则会报错!
greatmind829 2010-10-27
  • 打赏
  • 举报
回复
学习了。
树成 2009-05-27
  • 打赏
  • 举报
回复
我当然试过,不然也不会再这里跟你说了,你取不到值一定是其他地方有什么问题。类似的项目我做过很多的。
当然我是通过JDBC实现的,最后顺便说一句 seq_sqlsetence.nextval 你需要取一个别名,不然不好取值,例如语句这么写
select seq_sqlsetence.nextval as id from dual这样你就可以通过res.getString("ID");把值取出来了。
duanjianbo26 2009-05-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 spiniper 的回复:]
这纯粹属于一个步骤问题,你首先用select seq_sqlsetence.nextval from dual语句,获得主键值,然后保存在java程序中的一个变量中,然后写入主键的时候用这个值就可以了。
就算是hibernate自己也是这么实现的,hibernate的save方法返回主键值,如果你打开show_sql,你完全可以看见hibernate先执行select seq_sqlsetence.nextval from dual 语句,然后再执行insert into........这样的语句的。
[/Quote]
你说的步骤我也知道,但是select seq_sqlsetence.nextval from dual这就根本就取不到值!不信你试试
树成 2009-05-27
  • 打赏
  • 举报
回复
这纯粹属于一个步骤问题,你首先用select seq_sqlsetence.nextval from dual语句,获得主键值,然后保存在java程序中的一个变量中,然后写入主键的时候用这个值就可以了。
就算是hibernate自己也是这么实现的,hibernate的save方法返回主键值,如果你打开show_sql,你完全可以看见hibernate先执行select seq_sqlsetence.nextval from dual 语句,然后再执行insert into........这样的语句的。
fashi1000 2009-05-27
  • 打赏
  • 举报
回复
select seqname.currval from dual 查询序列当前值
select seqname.nextval from dual 查询序列下一值
sutdy 2009-05-27
  • 打赏
  • 举报
回复
nextval,currentval可以的
duanjianbo26 2009-05-27
  • 打赏
  • 举报
回复
好的,先谢过了!
super_roma 2009-05-26
  • 打赏
  • 举报
回复
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

public class OracleTest {

public static void main(String[] args) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = OracleConnectionFactory.getConnection();
DatabaseMetaData dmd = con.getMetaData();

System.out.println("database product name: " + dmd.getDatabaseProductName());
System.out.println("database product version: " + dmd.getDatabaseProductVersion());
System.out.println("supports generate keys? " + dmd.supportsGetGeneratedKeys());

String sql = "INSERT INTO t_mt_stat (id, mt_time, stat, stat_time) " +
"VALUES (s_mt_stat.nextval, ?, ?, ?)";

ps = con.prepareStatement(sql, new String[]{"ID"}); // 后面一个参数表示需要返回的列

ps.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
ps.setString(2, "Y");
ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
ps.executeUpdate();

if(dmd.supportsGetGeneratedKeys()) {
rs = ps.getGeneratedKeys();
while(rs.next()) {
// 如果使用 rs.getInt("ID") 会报错,奇怪的 Oracle JDBC 驱动!
System.out.println("ID: " + rs.getInt(1));
}
}

} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(rs, ps, con);
}
}
}
summerfeel 2009-05-26
  • 打赏
  • 举报
回复
建议你增加一个date型字段,保存记录插入的时间,查询的时候order by .. desc一下,取第一条记录
duanjianbo26 2009-05-26
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 zuguanqun 的回复:]
select seq_sqlsetence.currval from dual
[/Quote]
这样是不行的
zuguanqun 2009-05-19
  • 打赏
  • 举报
回复
select seq_sqlsetence.currval from dual
duanjianbo26 2009-05-19
  • 打赏
  • 举报
回复
那如果我不用PreparedStatement ,使用Statement可以吗?
duanjianbo26 2009-05-18
  • 打赏
  • 举报
回复
bao110908的认真负责让人佩服!
  • 打赏
  • 举报
回复
这个需要 JDBC 驱动程序支持,获得自动生成的列中值只有在支持 JDBC 3.0 规范的驱动程序才支持。

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

public class OracleTest {

public static void main(String[] args) {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = OracleConnectionFactory.getConnection();
DatabaseMetaData dmd = con.getMetaData();

System.out.println("database product name: " + dmd.getDatabaseProductName());
System.out.println("database product version: " + dmd.getDatabaseProductVersion());
System.out.println("supports generate keys? " + dmd.supportsGetGeneratedKeys());

String sql = "INSERT INTO t_mt_stat (id, mt_time, stat, stat_time) " +
"VALUES (s_mt_stat.nextval, ?, ?, ?)";

ps = con.prepareStatement(sql, new String[]{"ID"}); // 后面一个参数表示需要返回的列

ps.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
ps.setString(2, "Y");
ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
ps.executeUpdate();

if(dmd.supportsGetGeneratedKeys()) {
rs = ps.getGeneratedKeys();
while(rs.next()) {
// 如果使用 rs.getInt("ID") 会报错,奇怪的 Oracle JDBC 驱动!
System.out.println("ID: " + rs.getInt(1));
}
}

} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(rs, ps, con);
}
}
}
duanjianbo26 2009-05-15
  • 打赏
  • 举报
回复
不会吧,这也没人知道?
GeekZFZ 2009-05-14
  • 打赏
  • 举报
回复
看看这个:

package com.zfz.burke.dbutil;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DataBaseConnection {

//定义一个static类型的方法,用户连接数据库
public static Connection getConnection(){
Connection conn=null;
String url="jdbc:oracle:thin:@192.168.0.200:1521:mygod";
String uname="scott";
String upass="tiger";
String classname="oracle.jdbc.driver.OracleDriver";
//加载驱动
try {
Class.forName(classname);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取连接
try {
conn=DriverManager.getConnection(url,uname,upass);
System.out.println("--- 数据库连接已经建立成功...");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return conn;
}

}

package com.zfz.burke.model.daoimpl;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

import com.zfz.burke.dbutil.DataBaseConnection;
import com.zfz.burke.model.dao.DeptDAO;

public class DeptDAOImpl implements DeptDAO{

@Override
public boolean deleteDeptByDeptno(int deptno) {
// TODO Auto-generated method stub

boolean flag=false;

//建立与数据库的连接
Connection conn=DataBaseConnection.getConnection();
//编写调用存储过程的SQL语句
String callsql="{ call delDeptByDeptno(?,?)}";
//创建调用存储过程的语句集对象
java.sql.CallableStatement cs=null;
try {
cs=conn.prepareCall(callsql);
//cs对象需要设定参数
cs.setInt(1, deptno);
//cs对象注册存储过程种输出模式参数
cs.registerOutParameter(2, Types.VARCHAR);
//cs对象执行调用
cs.execute();
//获取执行结果
String result=cs.getString(2);

//执行业务处理
if(result.equals("部门删除成功")){
flag=true;
}else{
flag=false;
}


} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(cs!=null){
try {
cs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}



return flag;
}



}


package com.zfz.burke.model.daoimpl;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

import com.zfz.burke.dbutil.DataBaseConnection;
import com.zfz.burke.model.dao.EmpDAO;

public class EmpDAOImpl implements EmpDAO{




/*
* 通过调用PLSQL函数实现
*
* 函数的输入参数为:雇员姓名
* 函数的返回值为:该雇员的工资
* 函数的调用形式为:String sql="{ call ?:=function_name(参数)}";
* */

@Override
public double findSalOfEmpByEname(String ename) {
// TODO Auto-generated method stub
double result=-1;
//获取与数据库的连接
Connection conn=DataBaseConnection.getConnection();
//封装SQL语句
String sql="{call ?:=get_sal(?)}";
//获取调用的语句集
java.sql.CallableStatement cs=null;
try {
cs=conn.prepareCall(sql);
cs.setString(2, ename);
cs.registerOutParameter(1, Types.DOUBLE);
cs.execute();
result=cs.getDouble(1);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(cs!=null){
try {
cs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}



return result;
}

/*
* 通过这个方法按照给定的雇员编号,可以查询雇员的编号,姓名,工资信息
* 存储过程输入参数为:雇员编号(Number)
* 存储过程输出参数为:雇员编号(Number)、雇员姓名(varchar2)、雇员工资(number(7,2))
* 存储过程调用形式为:String sql="{call findEmpByEmpnoForJAVA(?,?,?,?)}";
* */
@Override
public void findEmpInfoByEmpno(int empno) {
// TODO Auto-generated method stub

//获取与数据库的连接
Connection conn=DataBaseConnection.getConnection();
//封装SQL语句
String sql="{call findEmpByEmpnoForJAVA(?,?,?,?)}";
//获取调用的语句集
java.sql.CallableStatement cs=null;
try {
cs=conn.prepareCall(sql);
//需要给设定的占位符号设置,并且注册Oracle存储过程输出模式参数值的类型
cs.setInt(1, empno);
//注册返回参数
cs.registerOutParameter(2, Types.INTEGER);
cs.registerOutParameter(3, Types.VARCHAR);
cs.registerOutParameter(4, Types.DOUBLE);
//执行
cs.execute();
//获取执行结果并打印输出
int eno=cs.getInt(2);
String ename=cs.getString(3);
double salary=cs.getDouble(4);
System.out.println ("雇员编号: "+eno+"\t雇员姓名: "+ename+"\t雇员工资: "+salary);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(cs!=null){
try {
cs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}




}

}


package com.zfz.burke.test;

import com.zfz.burke.model.daoimpl.DeptDAOImpl;

public class TestingDeptDAOImpl {


/*
* 测试删除执行部门信息的方法
* */


public static void testDeleteDeptByDeptno(int deptno){

DeptDAOImpl deptDAOImpl=new DeptDAOImpl();
boolean flag=deptDAOImpl.deleteDeptByDeptno(deptno);
if(flag){
System.out.println(deptno+" 号部门删除成功");
}else{
System.out.println(deptno+" 号部门删除失败");
}

}



/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
testDeleteDeptByDeptno(90);


}

}


package com.zfz.burke.test;

import com.zfz.burke.model.daoimpl.EmpDAOImpl;

public class TestingEmpDAOImpl {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
EmpDAOImpl empDAOImpl=new EmpDAOImpl();
//empDAOImpl.findEmpInfoByEmpno(7782);


//按照给定的雇员姓名,查找该雇员的工资
double res=empDAOImpl.findSalOfEmpByEname("smith");
System.out.println("Smith的工资为: "+res);
}

}


package com.zfz.burke.test;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.zfz.burke.dbutil.DataBaseConnection;

public class TestProcedureTHREE {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

Statement stmt = null;
ResultSet rs = null;
Connection conn = null;

try {

conn = DataBaseConnection.getConnection();

CallableStatement proc = null;
proc = conn.prepareCall("{ call scott.testc(?) }");
// 由于过程返回列表对象,即一个查询结果集,所以需要注册CURSOR类型的参数
proc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
//proc对象执行
proc.execute();
//获取执行以后的结果集
rs = (ResultSet) proc.getObject(1);

while (rs.next()) {
System.out.println("雇员编号: " + rs.getString(1) +" 雇员姓名: "
+ rs.getString(2) + " ");
}
} catch (SQLException ex2) {
ex2.printStackTrace();
} catch (Exception ex2) {
ex2.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
} catch (SQLException ex1) {
}
}

}

}


package com.zfz.burke.model.dao;

public interface DeptDAO {

//给定部门编号,删除指定的部门
public boolean deleteDeptByDeptno(int deptno);

}


package com.zfz.burke.model.dao;

public interface EmpDAO {

//定义一个调用Oracle存储过程返回单行记录的方法
public void findEmpInfoByEmpno(int empno);

//根据给定的雇员姓名,查找雇员工资的方法
public double findSalOfEmpByEname(String ename);


}


duanjianbo26 2009-05-14
  • 打赏
  • 举报
回复
分不够可以加!
duanjianbo26 2009-05-14
  • 打赏
  • 举报
回复
楼上的兄弟辛苦了,还不是不懂您的意思!调用存储过程?

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧