2013-07-03 5 views
4

세 개의 테이블 (team, player, team_player)이 있다고 가정 해 보겠습니다. 표 team_player는 "다 대다"관계를 허용하는 브리지 테이블입니다.트랜잭션 내 삽입 후 ID 가져 오기 (Oracle)

누군가 새로운 팀을 만들고 싶을 때, 팀에 초기 플레이어를 지정합니다.

동일한 트랜잭션에 team 및 team_player 행을 모두 삽입하려면 어떻게해야합니까? 즉, 새 팀 행에 커밋하기 전에 모든 team_player 레코드를 삽입하고 싶습니다. JDBC와 Oracle을 사용하고 있습니다.

아래 코드를 시도해도 teamIid가 숫자 (트리거에 의해 증가됨)인데도 teamId는 문자열로 채워집니다. 그래서, 이것은 제가 삽입하려고했던 레코드의 id가 아닌 것 같습니다. (아직 커밋하지 않았습니다.) 나는 RETURN_GENERATED_KEYS에 대해 읽어 경우

c = DB.getConnection(); 
c.setAutoCommit(false); 

sql = "INSERT INTO team (name) values (?)"; 
myInsert = c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 
myInsert.setString(1, "cougars"); 
int affectedRows = memoInsert.executeUpdate(); 

String teamId; 
ResultSet generatedKeys = myInsert.getGeneratedKeys(); 
if (generatedKeys.next()) { 
    teamId = generatedKeys.getString(1); 
} 

// ...loop through players inserting each player and team.id into team_player 

// c.commit(); 

이입니다 How to get the insert ID in JDBC?

+0

오라클은 시퀀스를 가지고있다. 이런 상황에서 잘 작동합니다. –

답변

10

Oracle JDBC 드라이버는 getGeneratedKeys()을 지원하지 않습니다. 트리거에서 수동으로 키를 생성하고 있습니다 (아마도 SEQUENCE).

당신은 오라클의 반환 조항 사용할 수 있습니다

String query = "BEGIN INSERT INTO team (name) values (?) returning id into ?; END;"; 
CallableStatement cs = conn.prepareCall(query); 
cs.setString(1, "cougars"); 
cs.registerOutParameter(2, OracleTypes.NUMBER); 
cs.execute(); 
System.out.println(cs.getInt(2)); 

을 또는 두 번째 SQL 쿼리와 마지막 시퀀스 번호를 잡아 :

SELECT mysequence.CURRVAL FROM dual 
+0

도움을 주셔서 감사합니다. 변수 이름으로 var를 대체해야합니까? 내가 ": var"를 그대로두면 IN 또는 OUT 매개 변수가 누락되었다는 오류가 발생합니다. ": var"를 "shinyNewId"로 바꾸면 매개 변수 유형 충돌에 대해 불평합니다. 나는 계속 그것에 찌를 것이다. – latj

+0

몇 가지 명백한 오류가 있었지만 답변이 수정되었습니다. 현재 잘 작동합니다. – samlewis

+0

이것은 효과가 있습니다. 그냥 호기심에서 ... 나는 완전히 이해하지 못하기 때문에 당신이 준 옵션 2를 피했다. 두 번째 쿼리를 수행하는 경우 다른 두 쿼리 사이에 다른 시퀀스가 ​​발생하면 잘못 될 수 있습니까? 어쨌든, 다시 한번 감사드립니다. – latj

0

Statement.getGeneratedKeys()을 참조하십시오 - 이것이 당신이 찾는 것을 믿고 다시 생성 - 열쇠의 결과 집합을 제공합니다.

기본적으로, 봄 JDBC는

덜 우아한 솔루션은 오라클의 RETURNING clause을 사용하는 것입니다 생성 된 식별자 (example from JdbcTemplate class)

를 검색하기 위해이 방법을 사용하지만, 당신은 다시 얻기 위해 저장된 프로 시저에 삽입 마무리 할거야 id

+0

그래, 내 질문에 코드 예제에서 getGeneratedKeys() 사용하고 있습니다. 문제는 이드가 아닌 것을 돌려 보내는 것입니다. 그것은 문자의 문자열입니다. 내 ID 필드는 숫자입니다. – latj

+1

ROWID가 반환됩니다. getGeneratedKeys 문서에 따르면 id를 나타내는 열이 지정되지 않은 경우 드라이버가이를 결정합니다. 분명히 Oracle의 경우 ROWID가됩니다. – diy

1

당신은 드라이버 열이 반환 말할 필요가있다. 당신의 ID가 트리거에 의해 채워지는 경우

다음 작동합니다 :

sql = "INSERT INTO team (name) values (?)"; 

// pass an array of column names to be returned by the driver instead of the int value 
// this assumes the column is named ID (I think it has to be all uppercase) 

myInsert = c.prepareStatement(sql, new String[]{"ID"}); 

myInsert.setString(1, "cougars"); 
int affectedRows = memoInsert.executeUpdate(); 

String teamId; 
ResultSet generatedKeys = myInsert.getGeneratedKeys(); 
if (generatedKeys.next()) { 
    teamId = generatedKeys.getString(1); 
} 
+0

매력처럼 작동합니다! 고맙습니다! –

+0

연결 상실로 인해 getGeneratedKeys()가 실패한 경우를 나타냅니다. 삽입 된 레코드를 롤백하는 방법은 무엇입니까? –

관련 문제