2011-05-19 8 views
9

私はこのように作成された私のMySQLデータベース、2つのテーブルがあります。JDBC:同じトランザクションで作成したPKの外部キー

CREATE TABLE table1 (
    id int auto_increment, 
    name varchar(10), 
    primary key(id) 
) engine=innodb 

CREATE TABLE table2 (
    id_fk int, 
    stuff varchar(30), 
    CONSTRAINT fk_id FOREIGN KEY(id_fk) REFERENCES table1(id) ON DELETE CASCADE 
) engine=innodb 

を(これらは、元のテーブルではありませんポイントは、table2がテーブル1のプライマリキーを参照する外部キーを持っているということです)

私のコードでは、1つのトランザクション内で両方のテーブルにエントリを追加したいと思います。だから私はfalseにautoCommitを設定します。

Connection c = null;   

    PreparedStatement insertTable1 = null; 
    PreparedStatement insertTable2 = null; 

    try { 
     // dataSource was retreived via JNDI 
     c = dataSource.getConnection(); 
     c.setAutoCommit(false); 

     // will return the created primary key 
     insertTable1 = c.prepareStatement("INSERT INTO table1(name) VALUES(?)",Statement.RETURN_GENERATED_KEYS); 
     insertTable2 = c.prepareStatement("INSERT INTO table2 VALUES(?,?)"); 

     insertTable1.setString(1,"hage"); 
     int hageId = insertTable1.executeUpdate(); 

     insertTable2.setInt(1,hageId); 
     insertTable2.setString(2,"bla bla bla"); 
     insertTable2.executeUpdate(); 

     // commit 
     c.commit(); 
    } catch(SQLException e) { 
     c.rollback(); 
    } finally { 
     // close stuff 
    } 

私は上記のコードを実行すると、私は例外を取得:

MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails 

私がコミットする前に、主キーがトランザクションで使用できないように思え。

ここに何か不足していますか?私は実際に生成された主キーがトランザクションで利用できるはずだと思います。

プログラムは、すべてのヘルプは本当に感謝されるのmysql-5.1.14コネクタとMySQL 5.5.8

を使用してGlassfishの3.0.1で実行されます!

よろしく、代わりのexecuteUpdateを(使用

HAGE

答えて

5

を行うことができ、あなたは、このようにしなければならない。

Long hageId = null; 

try { 
    result = insertTable1.executeUpdate(); 
} catch (Throwable e) { 
    ... 
} 

ResultSet rs = null; 

try { 
    rs = insertTable1.getGeneratedKeys(); 
    if (rs.next()) { 
     hageId = rs.getLong(1); 
    } 
... 
+0

ありがとう!それは今、完璧に動作します。しかし、何かは私にはまだ不明です:コードを実行する前に私のテーブルが空だった。そこで、 'exececuteUpdate'は、生成されたIDである影響を受けた行の数(この場合は1)を返します。私はこれがうまくいっているはずだと思う - それは2回目の実行で例外を発生させるだろう...または 'getGeneratedKeys()'はキーを利用できるようにするか? – hage

+0

テーブルに「切り捨て」を行わない限り、挿入された行IDは最後の行+ 1から始まり、0に初期化されません。 – EricParis16

+0

+1長時間この回答を探しています –

1

)は(実行)した後、プライマリ・キーを返す使用します。

http://www.coderanch.com/t/301594/JDBC/java/Difference-between-execute-executeQuery-executeUpdate

しかし、私はデシベルでは動作しません...ので、私はあなたが戻っ更新IDのために何かを逃し間違い

+0

私は異なるexecute *()メソッドの違いを知っています。私はちょうど間違った方法でキーを取得しようとしていた。私は 'Statement.RETURN_GENERATED_KEYS'が設定されているときに、executeUpdate()が変更された行の数ではなくキーを返すと考えました。とにかくあなたの答えに感謝します。 – hage

関連する問題