在SQL事务中获取实体的id字段

问题描述 投票:1回答:1

我有以下架构。

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

我想插入一个喜欢的项目。但是,我接受新用户的以下格式:(Pid, pname, bid, bname)

我想为此创建一个事务以避免冲突(这是我真正问题的高度简化版本,但问题是相同的)。在我的Person表中,我设置了pid自动增量(或Postgresql中的Serial)。 bid也是如此。

我已经陷入了一个问题,我知道人不存在,但啤酒存在。所以,我必须创建一个Person,然后将一个实体添加到Likes关系中。

据我所知,当我以dB为单位使用Autocommit(false)时,事务将在提交之前保存。那么,我应该更改数据库设计:

  • 将自动增量字段更改为普通整数,而不是空字段。
  • 在事务中,autoCommit(false)开始后,读取该人的最后一个条目
  • 创建新人时将其增加1
  • 然后创建喜欢的关系

或者,还有其他方法还是我想念交易?

这是我到目前为止所做的:

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();
}
postgresql jdbc transactions
1个回答
1
投票

您可以告诉JDBC从insert语句返回生成的ID,然后您可以使用该ID插入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();
© www.soinside.com 2019 - 2024. All rights reserved.