调用entityManager.flush-两次调用,一次调用或根本不调用的效果

时间:2019-06-17 14:07:42

标签: java spring jpa entitymanager

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

另外,如果我两次调用它,是否总是会出现无交易异常?

    @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?
    }

2 个答案:

答案 0 :(得分:1)

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

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

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

通常,不需要进行手动冲洗。我唯一能看到的实际收益是我的第二点,如果存在约束违例,必须立即停止执行。但是在我看来,这是一种代码味道,应该通过了解您可以做和不能做的更改以及正确的事务设置来轻松避免。

第二次调用flush,而在这之间没有任何更改,则不会产生任何效果,因为已经对数据库进行了所有更改。

答案 1 :(得分:1)

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

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

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