首页 > 解决方案 > 获取 SQL 事务中实体的 id 字段

问题描述

我有以下架构。

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

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

我想为此创建一个事务以避免冲突(这是我真正问题的高度简化版本,但问题是相同的)。在我的 Person 表中,我设置了pidAuto-Increment(或 Postgresql 中的 Serial)。也同样适用bid

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

据我所知,当我使用以 dB 为单位的 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();
}

标签: postgresqljdbctransactions

解决方案


您可以告诉 JDBC 从插入语句返回生成的 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();

推荐阅读