我有以下域对象:
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();
}
这是一个 Oracle 数据库。由于我要执行的步骤是插入所有猫,对我存档的猫进行合并,然后从插入的原始猫中删除所有记录。我担心的是,上面的这种方法不能保证回滚或单独操作的发生。我的问题是如何保证这一切都作为一个原子操作执行?此外,我如何保证没有其他函数接触数据库(就更新 Cat 表而言)不是读取?
最佳答案
原子性是 ACID 的一个特征数据库管理系统。它在 Oracle 中是自动的:运行所有 DML(更新/插入/删除),完成后发出提交。您可以保证操作将保存为不可分割的事务(如果提交失败,则不会保存任何内容)。
在 JDBC 中,您必须确保关闭自动提交。
关于并发性,它也是大多数 DBMS 的集成特性,尽管锁定的行为在主要 DBMS 之间可能有所不同。
在 Oracle 中,写入不会阻塞读取,尽管在您提交之前其他事务不会看到您的更改:这种隔离是通过 multi-versionning 实现的. DML 的锁定机制是行级的。只有一个事务可以同时修改一行。 Oracle 中一个工作单元的常见模式是:
- 选择要使用子句
FOR UPDATE
修改的行。这将锁定这些行,并且在您提交或回滚之前,其他事务将无法修改这些行。 - 无需中间提交即可执行所有 DML
- promise 成功或在出现错误时回滚。
进一步阅读:更多关于 transaction management , 更多信息 concurrency and locking .
锁定整个表在 Oracle 中很少见,尽管有可能。 LOCK TABLE命令可用于防止其他 session 对整个表的任何修改。
关于java - JDBC 通过 PreparedStatement 中的 executeBatch 调用保证原子操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11669498/