【问题标题】:Calling entityManager.flush - effects of calling it twice, once or not at all调用 entityManager.flush - 调用它两次、一次或根本不调用它的效果
【发布时间】:2019-10-31 03:34:16
【问题描述】:

我必须调用entityManager.flush() 还是在方法有@Transactional 注释时在退出时自动写入数据?

另外,如果我调用它两次,我总是会得到一个无事务异常吗?

    @PersistenceContext(unitName = "CONFIGURATION", type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

@Transactional
    public boolean generate() {
        doStuffToDatabase();
        //entitymanager.flush();
        //entitymanager.flush(); //If I call it twice do I always get a no transaction exception?
    }

【问题讨论】:

    标签: java spring jpa entitymanager


    【解决方案1】:

    当您更改事务中的实体时,您实际上并没有更改数据库,而是更改了行的内存模型。提交事务后,对内存模型的更改将刷新到数据库,这意味着将执行必要的 SQL 查询以将数据库状态变为模型状态。

    手动调用 entityManager.flush 时,您所做的就是在事务完成之前同步这些更改。这有几个含义:

    • 如果您的事务最终被取消(调用刷新后发生异常),Hibernate/JPA 将不得不执行数据库回滚,这将是性能成本
    • 如果您的模型状态最终违反了数据库中的约束,手动刷新将在较早阶段强制出现此错误。这通常会在您调用 flush 时中断 Java 的执行,而不是在事务提交时。

    一般来说,应该不需要手动冲洗。我能看到的唯一真正的收获是我在这里的第二点,如果有违反约束的情况,必须立即停止执行。但在我看来,这是一种代码异味,应该通过了解可以做什么和不可以做什么更改以及正确设置事务来轻松避免。

    再次调用flush,中间没有对模型进行任何更改,不会产生任何影响,因为所有更改都已对数据库进行。

    【讨论】:

      【解决方案2】:

      @Transactional 方法成功完成时,它将提交事务。在提交事务之前,如果不显式调用,它会在后台自动调用flush()

      flush() 将立即导致 JPA 发出 SQL 以插入或更新相关的数据库记录,如果在持久性上下文中有任何未决的更改。在第一次刷新后立即再次调用刷新是没有意义的,因为持久性上下文中的所有未决更改都已在第一次刷新时更新到数据库。

      当我们需要更新大量记录时,我们通常会手动调用flush(),以防止服务器内存不足。这个想法是,在对某些批次的记录进行更改后,我们刷新并清除持久性上下文,然后继续处理其他批次。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-15
        • 1970-01-01
        • 2014-10-29
        相关资源
        最近更新 更多