使用JDBC连接从oracle返回插入语句的ROWID参数

时间:2009-03-25 17:09:35

标签: 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 (some_id) VALUES (1) RETURNING ROWID INTO :rowid0");
st.registerReturnParameter(1, OracleTypes.ROWID);
st.execute();

我得到的错误是“违反协议”。如果我更改为registerOutParameter(),我会收到通知我没有注册所有返回变量。如果我将语句包装在PL / SQL中开始;结束;然后我使用常规的registerOutParameter()调用得到参数。我真的更愿意避免在PL / SQL中包装所有的insert语句 - 那么上面缺少什么?

5 个答案:

答案 0 :(得分:15)

通常您不希望依赖于代码数据库。您应该使用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);
}

答案 1 :(得分:6)

您需要做的一些事情

  • 将CallableStatement更改为OracleCallableStatement
  • 尝试并返回NUMBER,即: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);
    ...
  }
}

有关Oracle JDBC扩展的更多信息:

答案 2 :(得分:3)

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

来自Oracle Metalink:

<强>原因

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

根据JDBC FAQ: “10.1.0(10g r1)  DML返回是否受支持? 不在当前的驱动程序中。但是,我们确实计划在10.1.0之后的驱动程序中支持它。我们 这次真的很有意思。“

由于应用程序代码试图使用不受支持的JDBC功能,因此会引发错误。

<强>解决方案

将JDBC驱动程序升级到10.2.0.x,因为根据FAQ,10.2.0.x JDBC驱动程序支持返回子句:

“10.2.0(10g r2) DML返回是否受支持? 是!这是关于时间的。有关详细信息,请参阅开发人员指南。 “

修改 只是为了笑容,您可以检查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的支持请求是有序的......

答案 3 :(得分:1)

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

答案 4 :(得分:1)

PreparedStatement prepareStatement = connection.prepareStatement("insert...",
            new String[] { "your_primary_key_column_name" });

    prepareStatement.executeUpdate();

    ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
    if (null != generatedKeys && generatedKeys.next()) {
         Long primaryKey = generatedKeys.getLong(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);
    }

}

来源:http://viralpatel.net/blogs/oracle-java-jdbc-get-primary-key-insert-sql/