postgresql - 获取 SQL 事务中实体的 id 字段
问题描述
我有以下架构。
Person(pid, pname)
Beer(bid, bname)
Likes(pid,bid)
我想插入一个喜欢的项目。但是,我接受新用户的以下格式:(Pid, pname, bid, bname)
.
我想为此创建一个事务以避免冲突(这是我真正问题的高度简化版本,但问题是相同的)。在我的 Person 表中,我设置了pid
Auto-Increment(或 Postgresql 中的 Serial)。也同样适用bid
。
我陷入了一个我知道人不存在但啤酒存在的地步。所以,我必须创建一个 Person,然后将一个实体添加到 Likes 关系中。
据我所知,当我使用以 dB 为单位的 Autocommit(false) 时,事务在提交之前不会保存。那么,我应该更改数据库设计:
- 将自动增量字段更改为普通整数,而不是空字段。
- 在事务中,在 autoCommit(false) 开始后,读取 person 的最后一个条目
- 创建新人时将其加一
- 然后创建喜欢关系
或者,有没有其他方法或者我错过了一些关于交易的东西?
这是我到目前为止所做的:
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();
}
解决方案
您可以告诉 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();
推荐阅读
- arduino - Switch Case Arduino 的奇怪之处
- kotlin - Kotlin 函数引用是否有一个简单的空安全运算符?
- dart - Dart 私有数组
- amazon-dynamodb - 如何查询 AWS dynamodb 以获取每一小时、每一天和 30 天的数据?
- java - 我的 RecyclerViw 适配器出错,填充了 firebase 数据
- python - 如何执行存储在文件对象中的多个json对象
- linux - 为什么在这种情况下分配位置会导致无限循环?
- docker - 如何保存对 docker 容器和图像的更改
- java - 从发送到 AWS/Amazon SQS 的消息中删除无效字符
- bootstrap-4 - 关于 Accordion 的信息被推出,并且没有显示在 Bootstrap 上