对不起,这是一个很长的问题,但它触及了数据库的一般问题:
我正在使用sqlite / jdbc(在本例中),我正在尝试跟踪在向表中添加行时创建的自动ID。数据库有一个主表'Person'和其他名为'training'和'induction'的表。这个想法是人名和其他基本细节进入“人”表,而且一个人很多都有很多“训练”和“归纳”。所以,我可以通过SELECT * FROM INDUCTIONS WHERE PERSON_ID = any来查找给定人物的所有归纳。
问题在于创建数据库,我必须添加一个人,然后跟踪他们获得的AUTOINCREMENTing ID,然后在另一个表中创建具有该ID作为外键的条目:
所以
int id = 0;
PreparedStatement prepPerson = conn.prepareStatement("insert into persons values (?, ?);");
prepPerson.setString(2, p.getName());
prepPerson.addBatch();
然后
PreparedStatement prepInductions = conn.prepareStatement("insert into inductions values (?, ?, ?, ?);");
Then loop over all the inductions {
prepInductions.setInt(2, id);
prepInductions.setString(3, i.getSite());
prepInductions.setString(4, i.getExpiryDate());
prepInductions.addBatch();
}
我希望与数据库的交互是“原子的”,所以我想做
prepPerson.executeBatch();
prepInductions.executeBatch();
id++;
我意识到可以改为添加person,执行getGeneratedKeys(),然后使用新人的正确row_id添加导入,但我不希望在添加Person之后但在导入之前发生异常。如果发生这种情况,那么我将不得不回滚时间并将其移除。
目前我知道我每次都从外部源重新创建数据库,我用一个本地整数变量跟踪row_id,我知道这是生活危险。
这种情况不存在一般解决方案吗?或者我是否担心与数据库的“原子”交互?
答案 0 :(得分:2)
使用getGeneratedKeys()
检索生成的ID。
要保持数据完整性,请使用事务。通常,JDBC使用“autoCommit”模式,但在这种情况下,您需要手动处理事务。
在您的连接上致电.setAutoCommit(false)
,然后使用.commit()
和.rollback()
提交或放弃更改。
(检查Connection Javadoc。)
答案 1 :(得分:0)
对于这样的场景,一般框架是......
Begin A Transaction
Create your primary entry
Collect the auto-generated key
Create your child entries
Commit The Transaction
如果任何步骤失败,则允许您Rollback the Transaction
。
在SQLite中,我相信last_insert_rowid()
可用于在首次插入后获取自动生成的ID。
答案 2 :(得分:0)
您可以使用上面提供的代码,但请确保关闭自动提交。然后,您需要在加载所有人的导入后手动提交事务。如果遇到错误,请将其回滚。
这完全是原子的。