Отслеживание новых первичных ключей в SQL - PullRequest
0 голосов
/ 05 декабря 2011

Извините, это такой длинный вопрос, но он затрагивает общую проблему с базами данных:

Я использую sqlite / jdbc (в данном случае) и пытаюсь отслеживать автоматический идентификатор, созданный при добавлении строк в таблицу. База данных имеет основную таблицу «Персона» и другие таблицы, называемые «обучение» и «индукция». Идея состоит в том, что имена людей и другие базовые детали заносятся в таблицу «Персоны», и что у одного человека много «тренировок» и «индукций». Итак, я могу посмотреть все индукции для данного человека, выбрав SELECT * FROM INDUCTIONS WHERE PERSON_ID = что угодно.

Проблема заключается в создании базы данных, я должен добавить человека, затем отслеживать полученный им идентификатор AUTOINCREMENTing, а затем создать записи в другой таблице с этим идентификатором в качестве внешнего ключа:

So

int id = 0;    
PreparedStatement prepPerson = conn.prepareStatement("insert into persons values (?, ?);");
prepPerson.setString(2, p.getName());
prepPerson.addBatch();

Тогда

PreparedStatement prepInductions = conn.prepareStatement("insert into inductions values (?, ?, ?, ?);");

Then loop over all the inductions {
prepInductions.setInt(2, id);
prepInductions.setString(3, i.getSite());
prepInductions.setString(4, i.getExpiryDate());
prepInductions.addBatch();
}

Я хочу, чтобы взаимодействия с базой данных были «атомарными», поэтому я хочу сделать

prepPerson.executeBatch();
prepInductions.executeBatch();
id++;

Я понимаю, что вместо этого можно добавить человека, сделать getGeneratedKeys () и затем добавить индукции с правильным row_id нового человека, но я не хочу, чтобы исключение происходило после добавления человека, но до того, как индукции будут. Если это произойдет, мне придется откатиться назад и удалить человека.

На данный момент, насколько я знаю, я заново создаю базу данных из внешнего источника, я отслеживаю row_id с помощью локальной целочисленной переменной и знаю, что это опасно.

Нет ли общего решения для такой ситуации? Или меня сильно беспокоит «атомарное» взаимодействие с базой данных?

Ответы [ 3 ]

2 голосов
/ 05 декабря 2011

Используйте getGeneratedKeys() для получения сгенерированного идентификатора.

Чтобы сохранить целостность данных, используйте транзакции. Обычно JDBC использует режим 'autoCommit', но в этом случае вам придется обрабатывать транзакцию вручную.

Звоните .setAutoCommit(false) по вашему соединению и используйте .commit() и .rollback() для принятия или отмены изменений.

(Проверьте соединение Javadoc).

0 голосов
/ 05 декабря 2011

Вы можете использовать код, который вы указали выше, но убедитесь, что автокоммит выключен. Затем вам нужно вручную зафиксировать транзакцию после того, как все индукции этого человека были загружены. Или откатитесь, если вы столкнулись с ошибкой.

Это полностью атомно.

0 голосов
/ 05 декабря 2011

Для подобных сценариев общая структура - это ...

Begin A Transaction

 Create your primary entry
 Collect the auto-generated key
 Create your child entries

Commit The Transaction

Это тогда позволяет вам Rollback the Transaction, если какой-либо из шагов не пройден.

В SQLite, я полагаю last_insert_rowid() можно использовать для получения автоматически сгенерированного идентификатора после первой вставки.

...