Транзакция с двумя вставками sql - PullRequest
3 голосов
/ 09 октября 2009

У меня есть две вставки sql (скажем, для примеров в таблицах A и B), они находятся в транзакции, потому что я хочу, чтобы база данных оставалась согласованной, то есть кортеж в A должен иметь ссылки в B.

Во второй вставке мне нужен идентификатор, который идет от первого, но я не получаю этот идентификатор, пока не сделаю фиксацию для транзакции.
Так что я застрял. Я не хочу вынимать первую вставку из транзакции, может случиться так, что первая вставка пройдет нормально, а вторая - нет, оставив меня с несовместимым состоянием в базе данных.

Какова наилучшая практика в этой ситуации?

РЕДАКТИРОВАТЬ: Вот код:

TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
try{
    Integer aId = insertIntoA();
    insertIntoB(aId);
}catch(){
    transactionManager.rollback(txStatus);
    throw new CustomException(); 
}
transactionManager.commit(txStatus);

Я хочу отметить, что я не получаю aId , пока не совершу транзакцию, поэтому вставляю ноль в B.

Ответы [ 3 ]

2 голосов
/ 09 октября 2009

В MySQL, в insertIntoA вы должны иметь возможность:

SELECT LAST_INSERT_ID()

... на том же соединении, которое вы использовали для вставки, при условии, что вы ищете значение столбца identity.

РЕДАКТИРОВАТЬ : Если вы делаете это, и оно не работает (согласно вашему комментарию), я бы посмотрел на средние слои, чтобы увидеть, что происходит. С MySQL все в порядке:

mysql> create table A (id int(11) not null auto_increment, descr varchar(64), primary key (id));
Query OK, 0 rows affected (0.13 sec)

mysql> create table B (fk int(11) not null, descr varchar(64));
Query OK, 0 rows affected (0.06 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into A (descr) values ('Testing 1 2 3');
Query OK, 1 row affected (0.00 sec)

mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                1 |
+------------------+
1 row in set (0.03 sec)

mysql> insert into B (fk, descr) values (1, 'Test complete');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.03 sec)

mysql> select * from A;
+----+---------------+
| id | descr         |
+----+---------------+
|  1 | Testing 1 2 3 |
+----+---------------+
1 row in set (0.02 sec)

mysql> select * from B;
+----+---------------+
| fk | descr         |
+----+---------------+
|  1 | Test complete |
+----+---------------+
1 row in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into A (descr) values ('Second test');
Query OK, 1 row affected (0.01 sec)

mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

mysql> insert into B (fk, descr) values (2, 'Second test complete');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.08 sec)

mysql> select * from A;
+----+---------------+
| id | descr         |
+----+---------------+
|  1 | Testing 1 2 3 |
|  2 | Second test   |
+----+---------------+
2 rows in set (0.02 sec)

mysql> select * from B;
+----+----------------------+
| fk | descr                |
+----+----------------------+
|  1 | Test complete        |
|  2 | Second test complete |
+----+----------------------+
2 rows in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into A (descr) values ('We''ll roll this one back.');
Query OK, 1 row affected (0.00 sec)

mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
|                3 |
+------------------+
1 row in set (0.00 sec)

mysql> insert into B (fk, descr) values (3, 'Won''t see this one.');
Query OK, 1 row affected (0.00 sec)

mysql> select * from B;
+----+----------------------+
| fk | descr                |
+----+----------------------+
|  1 | Test complete        |
|  2 | Second test complete |
|  3 | Won't see this one.  |
+----+----------------------+
3 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.03 sec)

mysql> select * from A;
+----+---------------+
| id | descr         |
+----+---------------+
|  1 | Testing 1 2 3 |
|  2 | Second test   |
+----+---------------+
2 rows in set (0.00 sec)

mysql> select * from B;
+----+----------------------+
| fk | descr                |
+----+----------------------+
|  1 | Test complete        |
|  2 | Second test complete |
+----+----------------------+
2 rows in set (0.00 sec)
1 голос
/ 09 октября 2009

Какой идентификатор вы смотрите? Вы должны быть в состоянии получить, скажем, идентификаторы первичного ключа, автоматически генерируемые с помощью последовательностей (общий сценарий) независимо от состояния транзакции. Можете ли вы опубликовать код для уточнения?

0 голосов
/ 09 октября 2009

После первой вставки вы можете сделать

SELECT @@IDENTITY

Чтобы получить идентификатор строки, которую вы только что вставили?

...