2009-03-25 13 views
5

Me parece que no puede obtener la combinación mágica derecho de hacer este trabajo:Volver ROWID de parámetros de instrucción de inserción usando la conexión JDBC para Oracle


OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource(); 
ods.setURL("jdbc:oracle:thin:app_user/[email protected]: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(); 

El error que consigo es "Violación Protocolo". Si cambio a registerOutParameter(), me notifican que no he registrado todas las variables de devolución. Si envuelvo la declaración en un PL/SQL, empiece; fin; bloquear, entonces obtengo el parámetro muy bien usando una llamada normal registerOutParameter(). Realmente preferiría evitar envolver todas mis inserciones en PL/SQL, entonces, ¿qué falta desde arriba?

Respuesta

6

algunas cosas que usted tendrá que hacer

  • Cambio CallableStatement a OracleCallableStatement
  • intentar regresar en un número, es decir: OracleTypes.Número

Código de ejemplo para devolver información de una consulta:

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); 
    ... 
    } 
} 

Más información sobre las extensiones de JDBC de Oracle:

+0

[@kaido ha proporcionado una solución preferible que no depende de la base de datos] (http://stackoverflow.com/questions/682539/return-rowid-parameter-from- insert-statement-using-jdbc-connection-to-oracle/881414 # 881414). –

1

Intente utilizar ? en lugar de : rowid0 en su cadena SQL. He tenido problemas anteriormente con parámetros nombrados y Oracle.

3

No sé si esto aplica o no, ya que no especifica qué versión está utilizando.

De Oracle Metalink:

Causa

En el controlador JDBC 10.1.0.x, volviendo LMD no se admite:

por la AYUDA JDBC: "10.1.0 (10g r1) ¿Es compatible con DML? No está en los controladores actuales. Sin embargo, tenemos planes para admitirlo en los controladores posteriores a 10.1.0. Nosotros realmente lo decimos en esta ocasión ".

Como el código de la aplicación intenta utilizar funciones JDBC no compatibles, se producen errores.

Solución

actualizar el controlador JDBC para 10.2.0.x, porque por las preguntas frecuentes de los controladores JDBC 10.2.0.x apoyan cláusula de regresar:

"10.2.0 (r2 10g) es LMD Volviendo compatibles? SÍ! Y ya es hora. Consulte el manual del programador para más detalles. "

EDITAR Sólo para las muecas, se puede comprobar la versión de Oracle JDBC piensa que está utilizando con:

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

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

Si que muestra un controlador JDBC 10.2.0.x o temprano, entonces yo estoy fuera de ideas y tal vez una solicitud de soporte a Oracle es el fin ...

+0

Gracias por la información, aquí están las diferentes versiones que estoy usando: Java Versión: 1.6.0_12-b04 Versión de máquina virtual: 11.2-b01 (servidor de HotSpot) Servidor de Oracle: 10.2.0.4 Oracle Client: 11.1.0.7.0 hasta ojdbc6.jar – Goyuix

15

Por lo general, usted no quiere a hacer que la base de datos de código dependa En lugar de OraclePreparedStatement, debe usar CallableStatement.

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

Este azúcar sintáctico era exactamente lo que necesitaba - {call} –

+0

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Muchas gracias !!! – Gaucho

+0

Funcionó para mí también. Lo que hay que tener en cuenta es que si tiene un parámetro IN y un parámetro OUT, los índices siempre subirán. Entonces, si haces '{invocar INSERT INTO tbl (x, y) VALUES (seq.NEXTVAL,?) VOLVER x INTO? } 'then' seq.NEXTVAL' se devuelve en 'statement.getLong (2)', not 'getLong (1)'. – 0xbe5077ed

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); 
    } 

he encontrado la respuesta Esto es perfectamente funciona. Puedo insertar desde JAVA y su regreso con la clave.

Versión completa:

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; 

Y el código Java

String QUERY = "INSERT INTO students "+ 
       " VALUES (student_seq.NEXTVAL,"+ 
       "   'Harry', '[email protected]', '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); 
    } 

} 

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