2011-12-05 23 views
0

很抱歉,这是这么长的问题,但它倒是与数据库一般问题:比方追查

我使用SQLite/JDBC(在这种情况下),我试图跟踪在将行添加到表时创建的自动ID。数据库有一个主表'人'和其他表,称为'训练'和'归纳'。这个想法是,人名和其他基本的细节进入'人'表,并且一个人有许多'训练'和'诱导'。因此,我可以通过SELECT * FROM INDUCTIONS WHERE PERSON_ID = whatever来查找给定人的所有归纳。

的问题是创建数据库,我要加一个人,然后跟踪他们得到了自增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++; 

我意识到可以改为添加人,然后getGeneratedKeys(),然后添加具有新人的正确row_id的诱导,但我不希望在添加Person之后但在诱导是。如果发生这种情况,我必须回滚时间并将其移除。

目前我知道我每次都从外部源重新创建数据库,我跟踪了一个局部整型变量的row_id,我知道这是危险的生活。

这种情况没有一个通用的解决方案吗?还是我担心与数据库的“原子”交互?

+0

请澄清为什么优秀的旧交易不适合你。 AFAIK sqlite支持它们,setAutocommit(false)将隐式启动一个新的事务。 – Samuel

回答

2

请使用getGeneratedKeys()来检索生成的ID。

为了保持数据的完整性,请使用事务。通常,JDBC使用'autoCommit'模式,但在这种情况下,您需要手动处理事务。

在您的连接上拨打.setAutoCommit(false)并使用.commit().rollback()来提交或放弃更改。

(检查Connection Javadoc)。

+0

难道你不是指'rollback()'而不是'abort()'(后者旨在强制关闭连接)? –

+0

谢谢大家的快速回复。它现在是点击自动提交的关键。在执行批处理之前我已经将它设置为false,并按照例子将其设置为false,但却没有意识到原因 - 我根本没有'.commit()',但它仍然有效。所以一旦你完成了,你可以使用几个'.executeBatch()'和一个'.commit()'。这正是我需要的。解决了。 – djnz0feh

+0

@MarkRotteveel谢谢,'rollback()',当然是O :)。 – jjmontes

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。

0

您可以使用上面提供的代码,但要确保autocommit已关闭。然后,您需要在所有人员的导入装入后手动提交交易。如果遇到错误,请将其回滚。

这是完全原子的。