JDBC: внешний ключ на ПК создан в той же транзакции - PullRequest
9 голосов
/ 19 мая 2011

У меня есть две таблицы в моей базе данных MySQL, которые были созданы следующим образом:

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

(Это не оригинальные таблицы. Дело в том, что таблица2имеет внешний ключ, ссылающийся на первичный ключ в таблице 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

Любая помощьочень признателен!

С уважением, хаге

Ответы [ 2 ]

5 голосов
/ 19 мая 2011

Вы пропустили что-то для возвращенного обновленного идентификатора, вы должны сделать так:

Long hageId = null;

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

ResultSet rs = null;

try {
    rs = insertTable1.getGeneratedKeys();
    if (rs.next()) {
        hageId = rs.getLong(1);
    }
 ...
1 голос
/ 19 мая 2011

Вместо использования executeUpdate () используйте execute () и затем верните первичный ключ.

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

Но я не работаю с БД ... поэтому я могу ошибиться

...