Java 使用到oracle的JDBC连接从insert语句返回ROWID参数

Java 使用到oracle的JDBC连接从insert语句返回ROWID参数,java,oracle,jdbc,Java,Oracle,Jdbc,我似乎找不到合适的魔法组合来实现这一点: OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource(); ods.setURL("jdbc:oracle:thin:app_user/pass@server:1521:sid"); DefaultContext conn = ods.getConnection(); CallableStatement st = conn.prepareCall("INSERT INTO tableA

我似乎找不到合适的魔法组合来实现这一点:


OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource();
ods.setURL("jdbc:oracle:thin:app_user/pass@server:1521:sid");
DefaultContext conn = ods.getConnection();
CallableStatement st = conn.prepareCall("INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO :rowid0");
st.registerReturnParameter(1, OracleTypes.ROWID);
st.execute();

我得到的错误是“协议冲突”。如果我更改为registerOutParameter(),我会收到通知说我尚未注册所有返回变量。如果我将语句包装在PL/SQL begin中;结束;块,然后使用常规的registerOutParameter()调用获得参数。我真的希望避免将所有inserts语句包装在PL/SQL中—那么上面缺少了什么?

尝试在SQL字符串上使用而不是:rowid0。我以前在命名参数和Oracle方面遇到过问题。

不知道这是否适用,因为您没有指定使用的版本

从Oracle Metalink:

原因

在10.1.0.x JDBC驱动程序中,不支持返回DML:

根据JDBC常见问题解答: “10.1.0(10g r1) 是否支持DML返回? 不是在当前的驱动程序中。但是,我们有计划在10.1.0后的驱动程序中支持它。我们 这次是认真的。”

当应用程序代码试图使用不受支持的JDBC特性时,会出现错误

解决方案

将JDBC驱动程序升级到10.2.0.x,因为根据常见问题解答,10.2.0.x JDBC驱动程序确实支持returning子句:

“10.2.0(10g r2) 是否支持DML返回? 是的!是时候了。有关详细信息,请参阅《开发人员指南》。”

编辑 对于grins,您可以检查Oracle认为它正在使用的JDBC版本:

 // Create Oracle DatabaseMetaData object
  DatabaseMetaData meta = conn.getMetaData();

  // gets driver info:
  System.out.println("JDBC driver version is " + meta.getDriverVersion());

如果显示的是JDBC驱动程序10.2.0.x或更高版本,那么我就没有主意了,可能需要向oracle请求支持…

您需要做一些事情

  • 将CallableStatement更改为OracleCallableStatement
  • 尝试返回一个数字,即:OracleTypes.NUMBER
从查询返回信息的示例代码:

OraclePreparedStatement pstmt = (OraclePreparedStatement)conn.prepareStatement(
       "delete from tab1 where age < ? returning name into ?");
pstmt.setInt(1,18);

/** register returned parameter
  * in this case the maximum size of name is 100 chars
  */
pstmt.registerReturnParameter(2, OracleTypes.VARCHAR, 100);

// process the DML returning statement
count = pstmt.executeUpdate();
if (count>0)
{
  ResultSet rset = pstmt.getReturnResultSet(); //rest is not null and not empty
  while(rset.next())
  {
    String name = rset.getString(1);
    ...
  }
}
OraclePreparedStatement pstmt=(OraclePreparedStatement)conn.prepareStatement(
“从表1中删除,其中年龄<?将姓名返回?”);
pstmt.setInt(1,18);
/**寄存器返回参数
*在这种情况下,名称的最大大小是100个字符
*/
pstmt.registerReturnParameter(2,OracleTypes.VARCHAR,100);
//处理DML返回语句
count=pstmt.executeUpdate();
如果(计数>0)
{
ResultSet rset=pstmt.getReturnResultSet();//rest不为null且不为空
while(rset.next())
{
String name=rset.getString(1);
...
}
}
有关Oracle JDBC扩展的更多信息:


通常您不希望使代码依赖于数据库。您应该使用CallableStatement而不是OraclePreparedStatement

CallableStatement statement = connection.prepareCall("{call INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO ? }");
statement.registerOutParameter( 1, Types.VARCHAR );

int updateCount = statement.executeUpdate();
if (updateCount > 0) {
   return statement.getString(1);
}
我已经找到了答案,这是完美的作品。我可以从JAVA插入,并用键返回

完整版本:

CREATE TABLE STUDENTS
(
   STUDENT_ID   NUMBER NOT NULL PRIMARY KEY,
   NAME         VARCHAR2 (50 BYTE),
   EMAIL        VARCHAR2 (50 BYTE),
   BIRTH_DATE   DATE
);


CREATE SEQUENCE STUDENT_SEQ
   START WITH 0
   MAXVALUE 9999999999999999999999999999
   MINVALUE 0;
还有Java代码

String QUERY = "INSERT INTO students "+
               "  VALUES (student_seq.NEXTVAL,"+
               "         'Harry', 'harry@hogwarts.edu', '31-July-1980')";

// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");

// get database connection from connection string
Connection connection = DriverManager.getConnection(
        "jdbc:oracle:thin:@localhost:1521:sample", "scott", "tiger");

// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
        new String[] { "student_id" });

// local variable to hold auto generated student id
Long studentId = null;

// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {

    // getGeneratedKeys() returns result set of keys that were auto
    // generated
    // in our case student_id column
    ResultSet generatedKeys = ps.getGeneratedKeys();

    // if resultset has data, get the primary key value
    // of last inserted record
    if (null != generatedKeys && generatedKeys.next()) {

        // voila! we got student id which was generated from sequence
        studentId = generatedKeys.getLong(1);
    }

}

来源:

感谢您提供的信息,以下是我正在使用的各种版本:Java版本:1.6.0_12-b04虚拟机版本:11.2-b01(热点服务器)Oracle服务器:10.2.0.4 Oracle客户端:11.1.0.7.0到ojdbc6.jar这个语法糖正是我所需要的-{call}也为我工作。需要注意的是,如果你有一个IN参数和一个OUT参数,指数总是上升的。因此,如果您执行
{调用INSERT INTO tbl(x,y)值(seq.NEXTVAL),将x返回到}
中,那么
seq.NEXTVAL
将在
语句中返回。getLong(2)
,而不是
getLong(1)
。。
String QUERY = "INSERT INTO students "+
               "  VALUES (student_seq.NEXTVAL,"+
               "         'Harry', 'harry@hogwarts.edu', '31-July-1980')";

// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");

// get database connection from connection string
Connection connection = DriverManager.getConnection(
        "jdbc:oracle:thin:@localhost:1521:sample", "scott", "tiger");

// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
        new String[] { "student_id" });

// local variable to hold auto generated student id
Long studentId = null;

// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {

    // getGeneratedKeys() returns result set of keys that were auto
    // generated
    // in our case student_id column
    ResultSet generatedKeys = ps.getGeneratedKeys();

    // if resultset has data, get the primary key value
    // of last inserted record
    if (null != generatedKeys && generatedKeys.next()) {

        // voila! we got student id which was generated from sequence
        studentId = generatedKeys.getLong(1);
    }

}