2011-02-10 18 views
5

Soy nuevo en el uso de Oracle, por lo que estoy saliendo de lo que ya se ha respondido previamente en this SO question. Parece que no puedo hacer que funcione. Aquí está la declaración que estoy usando:Obtiene la última identificación de inserción con Oracle 11g usando JDBC

declare 
    lastId number; 
begin 
INSERT INTO "DB_OWNER"."FOO" 
    (ID, DEPARTMENT, BUSINESS) 
    VALUES (FOO_ID_SEQ.NEXTVAL, 'Database Management', 'Oracle') 
    RETURNING ID INTO lastId; 
end; 

Cuando llamo executeQuery PreparedStatement que he hecho, todo lo que se inserta en la base de datos muy bien. Sin embargo, parece que no puedo encontrar la manera de recuperar la ID. El objeto ResultSet devuelto no funcionará para mí. Llamando

if(resultSet.next()) ... 

produce una excepción de SQL desagradable que lee:

No se puede realizar traeré en un comunicado PLSQL: junto

¿Cómo consigo que lastId? Obviamente lo estoy haciendo mal.

+0

Siempre se puede consultar 'SELECCIONAR FOO_ID_SEQ.CURRVAL FROM DUAL'. – Phil

+2

Publique la función o el procedimiento almacenado; necesita saber si establece 'lastid' como un parámetro INOUT. –

+0

si tengo que ejecutar otra consulta, no estoy seguro de que sea la identificación del elemento que acabo de insertar. podría haber otra consulta que se coló allí. – geowa4

Respuesta

2

es una función que se lo devuelve (en lugar de un procedimiento). O bien, tenga un procedimiento con un parámetro OUT.

1

Cuando prepara el enunciado, establezca el segundo parámetro en RETURN_GENERATED_KEYS. Entonces debería poder obtener un ResultSet fuera del objeto de declaración.

+0

¿Es esto seguro para los hilos? –

+0

@James, posiblemente, pero eso parece una pregunta extraña, porque realmente no debería haber múltiples hilos trabajando con las mismas claves y declaraciones. ¿Podrías ampliar tu pregunta? – jzd

+0

Claro. Si tiene una sola instancia de DAO (sin sincronización) y más de una persona trabajando en una base de datos (algún tipo de aplicación de servidor), esto generaría un comportamiento poco confiable. Supongo que la base de datos devuelve este valor por orden de llegada, ¿sería adecuado para una sola aplicación de usuario? Supongo que el 'EntityManager' de Hibernate maneja cualquier problema con el estado (persistente o no) usando un patrón Proxy o algo similar. –

1

¿Lo estás haciendo en un procedimiento almacenado? De acuerdo con este Oracle document, no funcionará con el controlador del lado del servidor.

The Oracle server-side internal driver does not support 
the retrieval of auto-generated keys feature.
2

No estoy seguro si esto va a funcionar, ya que he purgado todos mis equipos de Oracle nada, pero ...

Cambiar la DECLARE para:

declare 
    lastId OUT number; 

Cambiar su estado de cuenta de un Estado Preparado a un Estado Callable utilizando prepareCall() en su conexión. A continuación, registrar el parámetro de salida antes de su llamada, y leerlo después de la actualización:

cstmt.registerOutParameter(1, java.sql.Types.NUMERIC); 
cstmt.executeUpdate(); 
int x = cstmt.getInt(1); 
+1

Esto debería funcionar, aunque la declaración debe contener una variable '?': Suelte la sección DECLARACIÓN, y reemplace 'DEVOLVER ID EN lastId' por' ¿DEVUELVE ID EN? '. También 'getInt' devuelve un int :) –

+0

Gracias - cambió el tipo de x de byte a int. –

1

Puede utilizar Statement.getGeneratedKeys() para hacer esto. Sólo tiene que asegurarse de que contar lo JDBC columnas que desea volver usando una de las sobrecargas de método para que, como la sobrecarga de Connection.prepareStatement aquí:

Connection conn = ... 
PreparedStatement pS = conn.prepareStatement(sql, new String[]{"id"}); 
pS.executeUpdate(); 
ResultSet rS = pS.getGeneratedKeys(); 
if (rS.next()) { 
    long id = rS.getLong("id"); 
    ... 
} 

No es necesario hacer las cosas RETURNING x INTO con esto, solo use la instrucción SQL básica que desee.

+1

long id = rS.getLong ("id"); es incorrecto: debe usar el índice de columna, en lugar del nombre (con oráculo) – Fisher

+0

@Fisher: Definitivamente estaba usando esta técnica (usando el nombre de columna) con Oracle. Quizás haya situaciones/versiones/configuraciones con Oracle en las que no funciona. – ColinD

2

Probé con el controlador Oracle v11.2.0.3.0 (ya que hay algunos errores en 10.x y 11.1.x, vea other blog). El siguiente código funciona bien:

final String sql = "insert into TABLE(SOME_COL, OTHER_COL) values (?, ?)"; 
PreparedStatement ps = con.prepareStatement(sql, new String[] {"ID"}); 
ps.setLong(1, 264); 
ps.setLong(2, 1); 
int executeUpdate = ps.executeUpdate(); 
ResultSet rs = ps.getGeneratedKeys(); 
if (rs.next()) { 
    // The generated id 
    long id = rs.getLong(1); 
    System.out.println("executeUpdate: " + executeUpdate + ", id: " + id); 
} 
Cuestiones relacionadas