Spring事务究竟是什么意思?

时间:2013-08-07 16:13:45

标签: java spring hibernate transactions

我对原子操作的理解是,操作步骤不应该与任何其他操作的步骤交错 - 它应该作为一个单元执行。

我有一个创建数据库记录的方法,首先检查具有相同值的记录(也满足某些其他参数)是否已经存在,如果是,则不会创建记录。

在假码中:

public class FooDao implements IFooDao {

    @Transactional
    public void createFoo(String fooValue) {
        if (!fooExists(fooValue)) {
            // DB call to create foo
        }
    }

    @Transactional
    public boolean fooExists(String fooValue) {
        // DB call to check if foo exists
    }
}

但是我已经看到可以创建具有相同值的两个记录,这表明这些操作已经以某种方式交错。我知道使用Spring的事务代理,对象内部方法的自调用不会使用事务逻辑,但如果从对象外部调用createFoo(),那么我希望fooExists()仍然包含在事务。

我对交易原子性应该执行错误的期望是什么?我是否需要使用同步块来强制执行此操作?

3 个答案:

答案 0 :(得分:1)

事务对数据库的真正意义取决于隔离级别。关于Isolation (database systems)的wikipdia文章解释得很清楚。

通常使用不太高的隔离级别,例如:Read committed。这意味着在提交其他事务之前,可以从其他事务中读取数据。 在你的情况下这还不够,因为这与你想要的相反。 - 所以显而易见的解决方案是使用更严格和更慢的隔离级别:Repeatable reads


但说实话,我会用另一种方式:使相关列唯一(但不要删除if (!fooExists(fooValue)) - 检查)。因此99%的检查工作。在剩余的1%中,您将获得异常,因为您试图违反唯一约束。

答案 1 :(得分:0)

事务性意味着所有更新都在同一事务中发生,即所有更新/插入/删除都成功或全部回滚(例如,如果更新多个表)。

它不保证事务中查询的行为,这取决于RDBMS及其配置(数据库上隔离级别的配置)。

答案 2 :(得分:0)

@Transactional默认情况下不会使代码同步。两个单独的线程可以同时进入同一个块并导致插入。同步该方法并不是一个好的答案,因为这可能会极大地影响应用程序性能。如果您的问题是由两个不同的线程创建了两个相同的记录,您可能希望在数据库中添加一些具有唯一约束的索引,以便重复插入失败。