Извлечение поля id объекта в транзакции SQL - PullRequest
1 голос
/ 16 апреля 2019

У меня есть следующая схема.

Person(pid, pname)
Beer(bid, bname)
Likes(pid,bid)

Я хотел бы вставить понравившийся элемент.Тем не менее, я принимаю следующий формат для новых пользователей: (Pid, pname, bid, bname).

Я хотел бы создать транзакцию для этого, чтобы избежать конфликта (Это очень упрощенная версия моей реальной проблемы, но проблема заключается в том,тот же самый).В моей таблице Person я установил pid Автоинкремент (или Serial в Postgresql).То же самое относится и к bid.

. Я застрял в точке, в которой я знаю, что Человек не существует, но пиво существует.Итак, мне нужно создать Person, а затем добавить сущность в отношение Likes.

Насколько я знаю, когда я использую Autocommit (false) в дБ, транзакция не будет сохранена до фиксации.Итак, я должен изменить дизайн БД:

  • Измените поле автоинкремента на обычное целое, а не нулевое поле.
  • В транзакции после того, как autoCommit (false) имеетначалось, прочитайте последнюю запись о человеке
  • Увеличьте ее на единицу при создании нового человека
  • Затем создайте отношение лайков

Или есть какой-то другой способили я что-то пропускаю по транзакциям?

Вот что я сделал до сих пор:

try {
    String add_person_sql = "INSERT INTO Person (name) VALUES(?)";
    PreparedStatement add_person_statement = mydb.prepareStatement(add_person_sql);

    String add_likes_sql = "INSERT INTO Likes (pid, bid) VALUES(?, ?)";
    PreparedStatement add_likes_statement = mydb.prepareStatement(add_likes_sql);

    mydb.setAutoCommit(false);

    add_person_statement.setString(1, pname);
    // The problem is, without saving the person I cannot know the id of the person

    // AFAIK, this execution is not finished until commit occurs
    add_person_statement.executeQuery();
    // How can I fetch person's id
    add_likes_statement.setString(1, pid); 
    add_likes_statement.setString(2, bid);

    add_likes_statement.executeQuery();

    mydb.commit();
}
catch(Exception e){
    System.out.println(e);
    mydb.rollback();
}

1 Ответ

1 голос
/ 16 апреля 2019

Вы можете указать JDBC возвращать сгенерированный идентификатор из оператора вставки, затем вы можете использовать этот идентификатор для вставки в таблицу likes:

mydb.prepareStatement(add_person_sql, new String[]{"pid"});

Второй параметр указывает драйверу возвращать сгенерированное значение для столбца pid.

В качестве альтернативы вы можете использовать

mydb.prepareStatement(add_person_sql, Statement.RETURN_GENERATED_KEYS);

, который указывает драйверу обнаруживать столбцы с автоинкрементом.

Затем запустите вставку, используя executeUpdate()

add_person_statement.setString(1, pname);
add_person_statement.executeUpdate();

int newPid = -1;
ResultSet idResult = add_person.getGeneratedKeys();
if (idResult.next()) {
   newPid = idResult.getInt(1);
}

add_likes_statement.setString(1, newPid); 
add_likes_statement.setString(2, bid);

add_likes_statement.executeUpdate();

mydb.commit();
...