2012-07-26 64 views
1
则ExecuteBatch呼叫保证原子操作

我有以下的域对象:JDBC通过内的PreparedStatement

class Cat 
{ 
    String name; 
    int age; 
} 

和下面的语句做猫的批量插入:

void insertBulkCats(Collection<Cat> cats) 
{ 
    Connection conn = getConnection(); 
    PreparedStatement statement = new PreparedStatement(); 
    for(Cat cat : cats) 
    { 
     statement.setString(1, cat.getName()); 
     statement.setInt(2, cat.getAge()); 
     statement.addBatch(); 
    }  
    statement.executeBatch(); 
    PreparedStatement mergeStatement = conn.prepareStatement(MERGE_CATS); 
    mergeStatement.execute(); 
    PreparedStatement dropStatement = conn.prepareStatement(CLEAR_CATS);  
    dropStatement.execute(); 
    conn.commit(); 
} 

这是一个甲骨文数据库。由于我想要执行的步骤是插入所有猫,对我的存档猫进行合并,然后删除插入的原始猫的所有记录。我担心的是,上述方法并不能保证发生回滚或单独操作。我的问题是我如何保证这一切都作为一个原子操作来执行?另外,如何保证没有其他函数触及数据库(对Cat表进行更新),而不是读取数据?

+0

你知道你必须执行你的'mergeStatement'和'dropStatement',不只是准备它们,对吗? – Olaf 2012-07-26 12:58:31

+0

@Olaf是的,我忘了包括那个,因为我正在用手抄录,显然没有一张名为Cat的表格。更新:) – Woot4Moo 2012-07-26 13:02:14

回答

7

原子性是ACID DBMS的一项功能。它在Oracle中是自动的:一旦完成提交,就运行所有的DML(更新/插入/删除)。您保证操作将被保存为不可分割的事务(如果提交失败,则不会保存任何内容)。

在JDBC中,您必须确保关闭自动提交

关于并发性,它也是大多数数据库管理系统的集成功能,尽管主要数据库管理系统的锁定行为可能不同。

在Oracle写入不要阻止读取,但其他事务将不会看到您的更改,直到您提交:此隔离通过multi-versionning实现。 DML的锁定机制处于行级别。只有一个事务可以同时修改一行。 Oracle在工作单元中的常见模式为:

  1. 选择要使用子句FOR UPDATE修改的行。这会对行进行锁定,其他事务将不能修改这些行,直到您提交或回滚。
  2. 做你所有的DML没有中间承诺
  3. 提交成功或在出现错误时回滚。

欲了解更多信息:更多关于transaction management,更多关于concurrency and locking

在Oracle中锁定整个表格很少见,尽管这是一种可能性。可以使用LOCK TABLE命令来阻止其他会话对整个表的任何修改。

+0

有趣。在关闭自动提交方面,以某种方式在语句中设置的位置或Connection对象? – Woot4Moo 2012-07-26 13:11:00

+0

使用['Connection.setAutocommit'](http://docs.oracle.com/javase/6/docs/api/java/sql/Connection.html#setAutoCommit(boolean)) – 2012-07-26 13:17:08

+0

感谢您的回答。 – Woot4Moo 2012-07-26 13:21:05