我有以下架构。
Person(pid, pname)
Beer(bid, bname)
Likes(pid,bid)
我想插入一个喜欢的项目。但是,我接受新用户的以下格式:(Pid, pname, bid, bname)
。
我想为此创建一个事务以避免冲突(这是我真正问题的高度简化版本,但问题是相同的)。在我的Person表中,我设置了pid
自动增量(或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();
}
您可以告诉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();