此文章来自http://blog.csdn.net/yzsind/article/details/6918506
Oracle的sequence实现非常灵活,所以也带来一些易用性问题,如何取到新插入记录生成的sequence值与其它数据库有较大差别,本文详国介绍了5种实现读取新插入记录sequence值的方法。
测试用的数据库脚本:
SQL> create table T1
(
ID NUMBER
);
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对象
|
作者:叶正盛
日期:2011-10-30
分享到:
相关推荐
在Java的JDBC4.0版本中,Oracle数据库的BLOB类型数据操作变得更加方便。BLOB(Binary Large Object)是用来存储大对象,如图像、音频或视频文件等二进制数据的数据库字段类型。以下是对使用JDBC4.0操作Oracle中BLOB...
在Java开发过程中,特别是在使用JDBC(Java Database Connectivity)与Oracle数据库交互时,处理BLOB(Binary Large Object)类型的数据是一项常见的需求。BLOB通常用于存储大量的二进制数据,如图像、音频或视频文件...
在数据同步过程中,如果需要保持两个数据库的主键一致,需要在插入Oracle时根据MySQL的最新主键值动态生成Oracle的序列号。 实现这个过程的具体步骤可能包括: 1. 查询MySQL的最新主键值,例如:`SELECT AUTO_...
- **序列(Sequence)**:在Oracle数据库中,序列是一种自动递增或递减的数字生成器,主要用于自动生成主键或唯一标识符。例如,`SEQNAME.NEXTVAL`用于获取序列的下一个值。 示例: ``` INSERT INTO test ...
在Oracle数据库中,JBPM使用特定的序列(Sequence)来生成主键。在Oracle模型中,序列名一般为`hibernate_sequence`。JBPM在Oracle数据库的配置需要指定相应的序列信息,并根据Oracle数据库的特点进行配置调整。 ##...
在Oracle中,虽然没有像MySQL那样的`AUTO_INCREMENT`关键字,但可以使用`SEQUENCE`对象来达到相同的效果,为新插入的记录自动提供唯一的ID。 `MyEclipse[1].6.Java.开发中文教程_免费电子版.pdf`可能包含MyEclipse ...
1. `CREATE SEQUENCE note_sequ`:这个语句创建了一个名为`note_sequ`的序列,序列在数据库中通常用来自动生成唯一ID,例如在插入新记录时作为主键的值。 2. `CREATE TABLE person`:创建了`person`表,包含三个...
例如:数据库查询条件的传入问题是所有ORM框架都不能回避的一个问题,所以我经常在想——既然我们可以用向DAO传入一个Entity来实现插入操作,为什么就不能用同样的方法来描述一个不以主键为条件的update/select/...
5. **批量操作**:支持批量插入、更新和删除,可以一次处理多条数据,提高数据库操作的效率。 6. **数据库兼容性**:MyBatis-Plus 兼容多种主流数据库,如 MySQL、Oracle、SQL Server、PostgreSQL 等,具有良好的跨...
- Increment:依赖于数据库的自动增长特性,如Oracle的Sequence,适合单进程环境,不适合并发更新。 - Identity:基于数据库的自动增长机制,如MySQL的auto_increment,适用于特定数据库,无需Hibernate参与,使用...
查询中包含了`TABLE`、`VIEW`、`INDEX`、`PROCEDURE`、`SEQUENCE`和`TRIGGER`这六种常见的数据库对象类型。 然后,Java程序连接到Oracle数据库,创建Statement对象并执行SQL查询。结果集中的每一行都包含了一个对象...
3. Increment:主键值通过自增方式生成,适用于支持Sequence的数据库(如Oracle、DB2)。不适用于多进程并发环境,因为可能导致主键冲突。 4. Identity:依赖于底层数据库的自动增长功能,如MySQL的auto_increment...
- **Sequence**:适用于支持序列的数据库,如Oracle和DB2,需要在映射文件中配置。 - **Identity**:依赖于数据库的自动增长功能,如MySQL的`auto_increment`或SQL Server的`Identity`。 **缓存管理** Hibernate...
- sequence:使用数据库序列,如Oracle。 - hilo:基于Hi/Lo算法的生成器,高效且避免数据库序列的开销。 - native:根据数据库类型选择合适的方式。 **五、Hibernate基本特性** - 对象-关系映射:提供了一种将...
- **Increment**:依赖数据库的自动增长功能,如Oracle和DB2的Sequence,适合单一数据库环境。 **缓存管理** - **一级缓存**:Session内部的缓存,自动管理,每次操作对象都会放入一级缓存。更新或删除对象后,...
- sequence:使用数据库序列,如Oracle。 - hilo:高位+低位算法,适用于大量主键生成,但需要配置表。 - native:根据底层数据库选择合适的策略。 - assigned:由应用程序指定,不自动生成。 **五、Hibernate基本...
其中,`native` 根据数据库类型选择相应的策略,`identity` 适用于SQL Server的自增长,`sequence` 用于Oracle的序列,`increment` 适合简单的主键自增,`uuid` 生成全局唯一的UUID字符串。 6. **JTA (Java ...