JDBC读取新插入Oracle数据库Sequence值的5种方法

Oracle的sequence实现非常灵活,所以也带来一些易用性问题,如何取到新插入记录生成的sequence值与其它数据库有较大差别,本文详国介绍了5种实现读取新插入记录sequence值的方法。

测试用的数据库脚本:

SQL> create table T1
  2  (
  3    ID NUMBER
  4  );

Table created
SQL> create sequence SEQ_T1;

Sequence created
//公共代码:得到数据库连接
public Connection getConnection() throws Exception{
    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:dbname", "username", "password");
    return conn;
}

//方法一
//先用select seq_t1.nextval as id from dual 取到新的sequence值。
//然后将最新的值通过变量传递给插入的语句:insert into t1(id) values(?)
//最后返回开始取到的sequence值。
//这种方法的优点代码简单直观,使用的人也最多,缺点是需要两次sql交互,性能不佳。
public int insertDataReturnKeyByGetNextVal() throws Exception {
    Connection conn = getConnection();
    String vsql = "select seq_t1.nextval as id from dual";
    PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql);
    ResultSet rs=pstmt.executeQuery();
    rs.next();
    int id=rs.getInt(1);
    rs.close();
    pstmt.close();
    vsql="insert into t1(id) values(?)";
    pstmt =(PreparedStatement)conn.prepareStatement(vsql);
    pstmt.setInt(1, id);
    pstmt.executeUpdate();
    System.out.print("id:"+id);
    return id;
}

//方法二
//先用insert into t1(id) values(seq_t1.nextval)插入数据。
//然后使用select seq_t1.currval as id from dual返回刚才插入的记录生成的sequence值。
//注:seq_t1.currval表示取出当前会话的最后生成的sequence值,由于是用会话隔离,只要保证两个SQL使用同一个Connection即可,对于采用连接池应用需要将两个SQL放在同一个事务内才可保证并发安全。
//另外如果会话没有生成过sequence值,使用seq_t1.currval语法会报错。
//这种方法的优点可以在插入记录后返回sequence,适合于数据插入业务逻辑不好改造的业务代码,缺点是需要两次sql交互,性能不佳,并且容易产生并发安全问题。
public int insertDataReturnKeyByGetCurrVal() throws Exception {
    Connection conn = getConnection();
    String vsql = "insert into t1(id) values(seq_t1.nextval)";
    PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql);
    pstmt.executeUpdate();
    pstmt.close();
    vsql="select seq_t1.currval as id from dual";
    pstmt =(PreparedStatement)conn.prepareStatement(vsql);
    ResultSet rs=pstmt.executeQuery();
    rs.next();
    int id=rs.getInt(1);
    rs.close();
    pstmt.close();
    System.out.print("id:"+id);
    return id;
}

//方法三
//采用pl/sql的returning into语法,可以用CallableStatement对象设置registerOutParameter取得输出变量的值。
//这种方法的优点是只要一次sql交互,性能较好,缺点是需要采用pl/sql语法,代码不直观,使用较少。
public int insertDataReturnKeyByPlsql() throws Exception {
    Connection conn = getConnection();
    String vsql = "begin insert into t1(id) values(seq_t1.nextval) returning id into :1;end;";
    CallableStatement cstmt =(CallableStatement)conn.prepareCall ( vsql);
    cstmt.registerOutParameter(1, Types.BIGINT);
    cstmt.execute();
    int id=cstmt.getInt(1);
    System.out.print("id:"+id);
    cstmt.close();
    return id;
}

//方法四
//采用PreparedStatement的getGeneratedKeys方法
//conn.prepareStatement的第二个参数可以设置GeneratedKeys的字段名列表,变量类型是一个字符串数组
//注:对Oracle数据库这里不能像其它数据库那样用prepareStatement(vsql,Statement.RETURN_GENERATED_KEYS)方法,这种语法是用来取自增类型的数据。
//Oracle没有自增类型,全部采用的是sequence实现,如果传Statement.RETURN_GENERATED_KEYS则返回的是新插入记录的ROWID,并不是我们相要的sequence值。
//这种方法的优点是性能良好,只要一次sql交互,实际上内部也是将sql转换成oracle的returning into的语法,缺点是只有Oracle10g才支持,使用较少。
public int insertDataReturnKeyByGeneratedKeys() throws Exception {
    Connection conn = getConnection();
    String vsql = "insert into t1(id) values(seq_t1.nextval)";
    PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql,new String[]{"ID"});
    pstmt.executeUpdate();
    ResultSet rs=pstmt.getGeneratedKeys();
    rs.next();
    int id=rs.getInt(1);
    rs.close();
    pstmt.close();
    System.out.print("id:"+id);
    return id;
}

//方法五
//和方法三类似,采用oracle特有的returning into语法,设置输出参数,但是不同的地方是采用OraclePreparedStatement对象,因为jdbc规范里标准的PreparedStatement对象是不能设置输出类型参数。
//最后用getReturnResultSet取到新插入的sequence值,
//这种方法的优点是性能最好,因为只要一次sql交互,oracle9i也支持,缺点是只能使用Oracle jdbc特有的OraclePreparedStatement对象。
public int insertDataReturnKeyByReturnInto() throws Exception {
    Connection conn = getConnection();
    String vsql = "insert into t1(id) values(seq_t1.nextval) returning id into :1";
    OraclePreparedStatement pstmt =(OraclePreparedStatement)conn.prepareStatement(vsql);
    pstmt.registerReturnParameter(1, Types.BIGINT);
    pstmt.executeUpdate();
    ResultSet rs=pstmt.getReturnResultSet();
    rs.next();
    int id=rs.getInt(1);
    rs.close();
    pstmt.close();
    System.out.print("id:"+id);
    return id;
}

以上5种方法都可以实现功能,以下是5种方法的优缺点汇总,个人推荐性能要求一般的业务采用第一种方法,性能要求非常高业务采用第五种方法。


方法


简介


优点


缺点


方法一


先用seq.nextval取出值,然后用转入变量的方式插入


代码简单直观,使用的人也最多


需要两次sql交互,性能不佳


方法二


先用seq.nextval直接插入记录,再用seq.currval取出新插入的值


可以在插入记录后返回sequence,适合于数据插入业务逻辑不好改造的业务代码


需要两次sql交互,性能不佳,并且容易产生并发安全问题


方法三


用pl/sql块的returning into语法,用CallableStatement对象设置输出参数取到新插入的值


只要一次sql交互,性能较好


需要采用pl/sql语法,代码不直观,使用较少


方法四


设置PreparedStatement需要返回新值的字段名,然后用getGeneratedKeys取得新插入的值


性能良好,只要一次sql交互


只有Oracle10g才支持,使用较少


方法五


returning into语法,用OraclePreparedStatement对象设置输出参数,再用getReturnResultSet取得新增入的值


性能最好,因为只要一次sql交互,oracle9i也支持


只能使用Oracle jdbc特有的OraclePreparedStatement对象

转载:http://blog.csdn.net/yzsind/article/details/6918506

时间: 2024-12-17 13:00:39

JDBC读取新插入Oracle数据库Sequence值的5种方法的相关文章

JDBC Insert语句插入Oracle数据库返回数据主键

表结构: create table test( id varchar2(32) primary key, name varchar2(32) ); import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Test { /** * 使用S

MYSQL插入处理重复键值的几种方法

当unique列在一个UNIQUE键上插入包含重复值的记录时,默认insert的时候会报1062错误,MYSQL有三种不同的处理方法,下面我们分别介绍. 先建立2个测试表,在id列上创建unique约束.mysql> create table test1(id int,name varchar(5),type int,primary key(id));Query OK, 0 rows affected (0.01 sec) mysql> create table test2(id int,na

oracle数据库中提供的5种约束

约束作用:用来保持数据的完整性,防止无效数据进入到数据库中.oracle数据库中提供的5种约束,都是限定某个列或者列的组合的.1.主键约束(PRIMARY KEY):在一个表中能唯一的标识一行.主键可以限定在多个列上.2.唯一键约束(UNIQUE key):在一个表中能唯一的标识一行,唯一键也可以限定在多个列上.主键和唯一键的区别:a.一个表中最多只能有一个主键.可以多个唯一键.b.主键所限定的列不能为null,唯一键所限定的列可以为null.3.外键约束(FOREIGN key):   引用表

VS中C#读取app.config数据库配置字符串的三种方法(转)

VS中C#读取app.config数据库配置字符串的三种方法(转) http://hi.baidu.com/mindox/item/3278dc352c7ba68fb80c0389 http://www.blogjava.net/keweibo/articles/391207.html 关于VS2008或VS2005中数据库配置字符串的三种取法 VS2008建立Form程序时,如果添加数据源会在配置文件 app.config中自动写入连接字符串,这个字符串将会在你利用DataSet,SqlDat

PHP获取MySql新增记录ID值的3种方法

From: http://www.jb51.net/article/51473.htm 这篇文章主要介绍了PHP获取MySql新增记录ID值的3种方法,一般使用PHP自带函数mysql_insert_id() 即可实现,另2种方法权作特殊情况下使用,需要的朋友可以参考下 一.使用语句: 复制代码 代码如下: mysql_query("select max(id) from t1",$link); 使用此方法得到的是 id最大的值,确为最后一个值,但当多链接线程时,这个最大的id并不一定

设置数据库兼容级别的两种方法以及区别

转:http://blog.csdn.net/htl258/article/details/5696325 --设置数据库兼容级别的两种方法 --以设置兼容SQL Serve 2005 为例 --法一: ALTER DATABASE database_name SET COMPATIBILITY_LEVEL = 90 GO --法二: EXEC sp_dbcmptlevel database_name,90 GO database_name 要修改为数据库的名称. 各参数值对应的数据库版本: 8

oracle rename数据文件的两种方法

oracle rename数据文件的两种方法 2012-12-11 20:44 10925人阅读 评论(0) 收藏 举报  分类: oracle(98)  版权声明:本文为博主原创文章,未经博主允许不得转载. 第一种 alter tablespace users rename datafile '==' to '***'; 这种方式需要数据库处于open状态,表空间在offline的状态下才能更改. [sql] view plain copy SQL> alter tablespace user

Activity的跳转及返回值 的四种方法

Activity生命周期 从创建到销毁的生命周期: onCreate()→onStart()→onResume()→onPouse()→onStop()→onDestroy() 从起动到后台再到前台: onCreate()→onStart()→onResume()→onPouse()→onStop()→onRestart()→onStart()→onResume() 启动第二个activity 1.创建new activity 2.创建对应的new xml布局文件 3.在new activity

MySQL数据库的备份与恢复的三种方法

MySQL数据库的备份与恢复的三种方法 1.利用mysqldump实现从逻辑角度完全备份mysql,配合二进制日志备份实现增量备份 2.利用lvs快照从物理角度实现几乎热备的完全备份,配合二进制日志备份实现增量备份 3.利用percona公司的xrabackup实现完全热备份与增量热备份 实验环境:RHEL5.8 ,SElinux关闭,MySQL是tar包初始化安装版本5.5.28 一.测试环境准备 1.1 mysql的安装就不说了,见http://laoguang.blog.51cto.com