【问题标题】:Fetching id field of an entity in the SQL Transaction获取 SQL 事务中实体的 id 字段
【发布时间】:2019-09-06 04:45:38
【问题描述】:

我有以下架构。

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

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

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

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

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

【问题讨论】:

  • "在创建新人时将其增加一" 这样做这样做。它很慢,更糟糕的是,它无法正常工作。

标签: postgresql jdbc transactions


【解决方案1】:

您可以告诉 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();

【讨论】:

  • 所以,jdbc 可以返回值,即使事务没有完成(未提交)
  • @qds52625:是的。它本质上是使用INSERT INTO .... RETURNING ... 声明postgresql.org/docs/current/sql-insert.html#id-1.9.3.152.5
  • 谢谢,@a_horse_with_no_name。我还有一件事要问:CREATE TABLE Person( pid SERIAL, name TEXT, PRIMARY KEY (pid) ); 当我尝试在此表中插入时,JDBC 向我返回错误:detailMessage "ERROR: 重复键值违反唯一约束 "Person_pkey"\n 详细信息:键 (pid)=(1 ) 已经存在。” (id=66)
  • @qds52625:然后您通过自己提供 ID 值插入到表中,并且序列不同步。 stackoverflow.com/questions/244243
  • 好的,多亏了你,我想通了。在数据库的填充步骤中,我正在设置 ID。我把工作交给了 postgresql,它工作正常。非常感谢
猜你喜欢
  • 1970-01-01
  • 2015-09-26
  • 2011-12-31
  • 2016-02-16
  • 2023-04-01
  • 1970-01-01
  • 2015-09-01
  • 2022-01-07
  • 1970-01-01
相关资源
最近更新 更多