2011-05-19 47 views
9

創建我有我的MySQL數據庫,並進行了這樣的創建兩個表: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中的主鍵)

現在在我的代碼中,我想添加條目到一個事務中的兩個表。所以我設置autoCommit爲false:

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 

看來我以前犯類似的主鍵是不是在交易中使用。

我在這裏錯過了什麼嗎?我真的認爲生成的主鍵應該在事務中可用。

程序上的Glassfish 3.0.1運行使用MySQL的連接器5.1.14和MySQL 5.5.8

任何幫助,非常感謝!

問候, 哈哥

回答

5

你錯過了一些用於返回更新的ID,你必須這樣做:

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'返回了受影響的行數(在本例中爲1),這也是生成的ID。我認爲這也應該起作用 - 它也會在第二次運行中引發異常......或者'getGeneratedKeys()'使密鑰可用? – hage 2011-05-19 12:36:07

+0

插入的行ID從最後一行開始+1,除非你在表格上做了'truncate',它不會初始化爲0. – EricParis16 2011-05-21 17:50:42

+0

+1我正在長時間看這個答案 – 2013-07-03 11:27:08

1

代替使用的executeUpdate的()的使用執行(),然後返回主鍵。

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

但我不使用DB工作...所以我可以做一個錯誤

+0

我知道不同的execute *()方法之間的區別。我只是想以錯誤的方式得到鑰匙。我認爲在設置'Statement.RETURN_GENERATED_KEYS'時,executeUpdate()會返回鍵值而不是已更改的行數。不過謝謝你的回答。 – hage 2011-05-19 13:58:54