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

测试用的数据库脚本:

  1. SQL> create table T1
  2. 2 (
  3. 3 ID NUMBER
  4. 4 );
  5.  
  6. Table created
  7. SQL> create sequence SEQ_T1;
  8.  
  9. Sequence created
  1. //公共代码:得到数据库连接
  2. public Connection getConnection() throws Exception{
  3. Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
  4. Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:dbname", "username", "password");
  5. return conn;
  6. }
  7.  
  8. //方法一
  9. //先用select seq_t1.nextval as id from dual 取到新的sequence值。
  10. //然后将最新的值通过变量传递给插入的语句:insert into t1(id) values(?)
  11. //最后返回开始取到的sequence值。
  12. //这种方法的优点代码简单直观,使用的人也最多,缺点是需要两次sql交互,性能不佳。
  13. public int insertDataReturnKeyByGetNextVal() throws Exception {
  14. Connection conn = getConnection();
  15. String vsql = "select seq_t1.nextval as id from dual";
  16. PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql);
  17. ResultSet rs=pstmt.executeQuery();
  18. rs.next();
  19. int id=rs.getInt(1);
  20. rs.close();
  21. pstmt.close();
  22. vsql="insert into t1(id) values(?)";
  23. pstmt =(PreparedStatement)conn.prepareStatement(vsql);
  24. pstmt.setInt(1, id);
  25. pstmt.executeUpdate();
  26. System.out.print("id:"+id);
  27. return id;
  28. }
  29.  
  30. //方法二
  31. //先用insert into t1(id) values(seq_t1.nextval)插入数据。
  32. //然后使用select seq_t1.currval as id from dual返回刚才插入的记录生成的sequence值。
  33. //注:seq_t1.currval表示取出当前会话的最后生成的sequence值,由于是用会话隔离,只要保证两个SQL使用同一个Connection即可,对于采用连接池应用需要将两个SQL放在同一个事务内才可保证并发安全。
  34. //另外如果会话没有生成过sequence值,使用seq_t1.currval语法会报错。
  35. //这种方法的优点可以在插入记录后返回sequence,适合于数据插入业务逻辑不好改造的业务代码,缺点是需要两次sql交互,性能不佳,并且容易产生并发安全问题。
  36. public int insertDataReturnKeyByGetCurrVal() throws Exception {
  37. Connection conn = getConnection();
  38. String vsql = "insert into t1(id) values(seq_t1.nextval)";
  39. PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql);
  40. pstmt.executeUpdate();
  41. pstmt.close();
  42. vsql="select seq_t1.currval as id from dual";
  43. pstmt =(PreparedStatement)conn.prepareStatement(vsql);
  44. ResultSet rs=pstmt.executeQuery();
  45. rs.next();
  46. int id=rs.getInt(1);
  47. rs.close();
  48. pstmt.close();
  49. System.out.print("id:"+id);
  50. return id;
  51. }
  52.  
  53. //方法三
  54. //采用pl/sql的returning into语法,可以用CallableStatement对象设置registerOutParameter取得输出变量的值。
  55. //这种方法的优点是只要一次sql交互,性能较好,缺点是需要采用pl/sql语法,代码不直观,使用较少。
  56. public int insertDataReturnKeyByPlsql() throws Exception {
  57. Connection conn = getConnection();
  58. String vsql = "begin insert into t1(id) values(seq_t1.nextval) returning id into :1;end;";
  59. CallableStatement cstmt =(CallableStatement)conn.prepareCall ( vsql);
  60. cstmt.registerOutParameter(1, Types.BIGINT);
  61. cstmt.execute();
  62. int id=cstmt.getInt(1);
  63. System.out.print("id:"+id);
  64. cstmt.close();
  65. return id;
  66. }
  67.  
  68. //方法四
  69. //采用PreparedStatement的getGeneratedKeys方法
  70. //conn.prepareStatement的第二个参数可以设置GeneratedKeys的字段名列表,变量类型是一个字符串数组
  71. //注:对Oracle数据库这里不能像其它数据库那样用prepareStatement(vsql,Statement.RETURN_GENERATED_KEYS)方法,这种语法是用来取自增类型的数据。
  72. //Oracle没有自增类型,全部采用的是sequence实现,如果传Statement.RETURN_GENERATED_KEYS则返回的是新插入记录的ROWID,并不是我们相要的sequence值。
  73. //这种方法的优点是性能良好,只要一次sql交互,实际上内部也是将sql转换成oracle的returning into的语法,缺点是只有Oracle10g才支持,使用较少。
  74. public int insertDataReturnKeyByGeneratedKeys() throws Exception {
  75. Connection conn = getConnection();
  76. String vsql = "insert into t1(id) values(seq_t1.nextval)";
  77. PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql,new String[]{"ID"});
  78. pstmt.executeUpdate();
  79. ResultSet rs=pstmt.getGeneratedKeys();
  80. rs.next();
  81. int id=rs.getInt(1);
  82. rs.close();
  83. pstmt.close();
  84. System.out.print("id:"+id);
  85. return id;
  86. }
  87.  
  88. //方法五
  89. //和方法三类似,采用oracle特有的returning into语法,设置输出参数,但是不同的地方是采用OraclePreparedStatement对象,因为jdbc规范里标准的PreparedStatement对象是不能设置输出类型参数。
  90. //最后用getReturnResultSet取到新插入的sequence值,
  91. //这种方法的优点是性能最好,因为只要一次sql交互,oracle9i也支持,缺点是只能使用Oracle jdbc特有的OraclePreparedStatement对象。
  92. public int insertDataReturnKeyByReturnInto() throws Exception {
  93. Connection conn = getConnection();
  94. String vsql = "insert into t1(id) values(seq_t1.nextval) returning id into :1";
  95. OraclePreparedStatement pstmt =(OraclePreparedStatement)conn.prepareStatement(vsql);
  96. pstmt.registerReturnParameter(1, Types.BIGINT);
  97. pstmt.executeUpdate();
  98. ResultSet rs=pstmt.getReturnResultSet();
  99. rs.next();
  100. int id=rs.getInt(1);
  101. rs.close();
  102. pstmt.close();
  103. System.out.print("id:"+id);
  104. return id;
  105. }

以上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

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

  1. Oracle 数据库分页查询的三种方法

    一.Oracle 数据库分页查询的三种方法 1.简介 不能对 rownum 使用 >(大于或等于 1 的数值).>=(大于 1 的数值).=(不等于 1 的数值),否则无结果.所以直接用 ...

  2. 【Java EE 学习 29 下】【JDBC编程中操作Oracle数据库】【调用存储过程的方法】

    疑问:怎样判断存储过程执行之后返回值是否为空. 一.连接oracle数据库 1.需要的jar包:在安装的oracle中就有,所以不需要到官网下载,我的oracle11g下:D:\app\kdyzm\p ...

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

    当unique列在一个UNIQUE键上插入包含重复值的记录时,默认insert的时候会报1062错误,MYSQL有三种不同的处理方法,下面我们分别介绍. 先建立2个测试表,在id列上创建unique约 ...

  4. jdbc连接rac的oracle数据库

    jdbc连接rac的oracle数据库需要配置所有racIP,如下: DB1 =(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(H ...

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

    约束作用:用来保持数据的完整性,防止无效数据进入到数据库中.oracle数据库中提供的5种约束,都是限定某个列或者列的组合的.1.主键约束(PRIMARY KEY):在一个表中能唯一的标识一行.主键可 ...

  6. MySQL数据库分表的3种方法

    原文地址:MySQL数据库分表的3种方法作者:dreamboycx 一,先说一下为什么要分表 当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目 ...

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

    From: http://www.jb51.net/article/51473.htm 这篇文章主要介绍了PHP获取MySql新增记录ID值的3种方法,一般使用PHP自带函数mysql_insert_ ...

  8. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  9. 【MySQL】锁——查看当前数据库锁请求的三种方法 20

    MySQL提供了查看当前数据库锁请求的三种方法:1. show  full  processlist命令  观察state和info列 2. show engine  innodb status\G ...

随机推荐

  1. css - float浮动模块的高度问题 解决方案

    当一个Div中的子元素都是浮动元素时,该div是没有高度的.通常会带来很多困扰,解决方案如下: 低版本统配兼容: overflow: hidden; 下面是不支持低配浏览器,而且似乎该效果对 P 标签 ...

  2. html - 自动播放音乐

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. poj3292-Semi-prime H-numbers(筛法打表)

    一,题意:  一个H-number是所有的模四余一的数.(x=4*k+1)  如果一个H-number是H-primes 当且仅当它的因数只有1和它本身(除1外). 一个H-number是H-semi ...

  4. Samba配置

    https://wiki.samba.org/index.php/Samba_AD_DC_Port_Usage 安装后开放端口 1    ACCEPT     tcp  --  0.0.0.0/0   ...

  5. libgdx actor 透明问题

    遇到一个问题,自定义的Actor在使用batch.draw时,其他Actor设置的透明影响到了这个Actor 处理方法为 在自定义Actor中 draw方法中 绘制前,加入 Color color = ...

  6. spring02

    1.在spring容器中的一个bean的整个生命周期 1.启动spring容器 2.bean实例化 3.装配属性 4.BeanNameAware:setBeanName 5.BeanFactoryAw ...

  7. MySQL基础CRUD编程练习题的自我提升(1)

    基础知识: 1.数据库的连接 mysql -u -p -h -u 用户名 -p 密码 -h host主机 2:库级知识 2.1 显示数据库: show databases; 2.2 选择数据库: us ...

  8. Java 集合的基本用法

    package jaxpsax; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; i ...

  9. Secretary Problem

    最好时机问题 n个值 前n/e都不选 然后取第一个大于前n/e个数中最大值的数 选中最大的概率为1/e

  10. 。。。在学习新框架Spring MVC的感受。。。

    已经学习一遍Spring MVC了,感觉还是懵懵懂懂的,特别是重定向,路径,参数的这些问题,心好乱,不过,这,都不是问题!!! 继续努力,努力到会为止!!!加油!!!