2011-02-10 15 views
5

Jestem nowy w używaniu Oracle, więc wychodzę z tego, co już zostało wcześniej odebrane w this SO question. Po prostu nie mogę tego zmusić do działania. Oto oświadczenie, że używam:Pobierz ostatni identyfikator wstawki z Oracle 11g, używając 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; 

Kiedy zadzwonić executeQuery PreparedStatement że zrobiłem, to wkłada wszystko do bazy danych po prostu grzywny. Jednak nie mogę wymyślić, jak pobrać identyfikator. Zwrócony obiekt ResultSet nie będzie dla mnie działał. Wywołanie

if(resultSet.next()) ... 

daje paskudny SQLException, który brzmi:

Nie można wykonać sprowadzić na oświadczenia PLSQL: Następna

Jak mogę dostać że lastId? Oczywiście robię to źle.

+0

Zawsze możesz zapytać 'SELECT FOO_ID_SEQ.CURRVAL FROM DUAL'. – Phil

+2

Opublikuj funkcję lub procedurę przechowywaną - musisz wiedzieć, czy ustawiłeś 'lastid' jako parametr INOUT. –

+0

jeśli muszę wykonać inne zapytanie, nie mam gwarancji, że jest to identyfikator elementu, który właśnie wstawiłem. może tam być inne zapytanie. – geowa4

Odpowiedz

2

sprawiają, że funkcja ta zwraca go do ciebie (zamiast procedury). Lub wykonaj procedurę z parametrem OUT.

1

Po przygotowaniu instrukcji ustaw drugi parametr na RETURN_GENERATED_KEYS. Wtedy powinieneś być w stanie uzyskać ResultSet z obiektu instrukcji.

+0

Czy to jest bezpieczne dla wątków? –

+0

@ James, być może, ale wydaje się dziwne pytanie, ponieważ naprawdę nie powinieneś mieć wielu wątków pracujących z tymi samymi kluczami i instrukcjami. Czy możesz rozwinąć swoje pytanie? – jzd

+0

Pewnie. Jeśli masz jedną instancję DAO (bez synchronizowania) i więcej niż jedną osobę pracującą na bazie danych (jakaś aplikacja serwera), może to spowodować niewiarygodne zachowanie. Zakładam, że baza danych zwraca tę wartość na zasadzie "kto pierwszy, ten lepszy", czy pasuje do aplikacji pojedynczego użytkownika? Przypuszczam, że "EntityManager" Hibernate radzi sobie ze wszystkimi problemami ze stanem (trwały lub nie), używając wzorca proxy lub czegoś podobnego. –

1

Czy robisz to w procedurze przechowywanej? Zgodnie z tym Oracle document, nie będzie działać ze sterownikiem po stronie serwera.

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

Nie wiem, czy to będzie działać, odkąd oczyszczone wszystkich moich komputerach niczego Oracle, ale ...

Zmień deklarują:

declare 
    lastId OUT number; 

przełączyć oświadczenie od PreparedStatement do CallableStatement za pomocą metody prepareCall() w twoim połączeniu. Następnie zarejestrować parametr wyjściowy przed rozmowy i czytać ją po aktualizacji:

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

To powinno zadziałać, chociaż instrukcja musi zawierać zmienną '?': Zrzucić sekcję DECLARE i zamienić "ID ZWRÓCENIA W IDENTYFIKOWANĄ NAZWĘ" na "ID ZWROTU?". Również 'getInt' zwraca int :) –

+0

Dzięki - zmieniono typ x z bajtu na int. –

1

Statement.getGeneratedKeys() Można użyć do tego celu. Musisz tylko upewnić się, aby powiedzieć JDBC jakie kolumny chcesz z powrotem przy użyciu jednego z przeciążeniem metoda, że ​​takich jak Connection.prepareStatement przeciążenia tutaj:

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

Nie trzeba robić RETURNING x INTO rzeczy z tego, po prostu użyj podstawowej instrukcji SQL, którą chcesz.

+1

long id = rS.getLong ("id"); jest źle - musisz użyć indeksu kolumny, zamiast nazwy (z oracle) – Fisher

+0

@Fisher: Zdecydowanie używałem tej techniki (używając nazwy kolumny) w Oracle. Być może są sytuacje/wersje/konfiguracje z Oracle, w którym to nie działa. – ColinD

2

Próbowałem ze sterownikiem Oracle v11.2.0.3.0 (ponieważ są pewne błędy w 10.x i 11.1.x, patrz other blog). Poniższy kod działa poprawnie:

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); 
} 
Powiązane problemy