Entitymanager.flush()VS EntityManager.getTransaction().commit - 我应该更喜欢什么?

Rox*_*Rox 44 java jpa eclipselink

更新数据库时我应该更喜欢什么?两种方法的优缺点是什么?何时使用其中一种方法?

public void disemployEmployee(Integer employeeId, Date endDate) {
    Employee employee = (Employee)em.find("Employee", employeeId);
    employee.getPeriod().setEndDate(endDate);
    em.flush();
}

public void disemployEmployee(Integer employeeId, Date endDate) {
    Employee employee = (Employee)em.find("Employee", employeeId);
    em.getTransaction().begin();
    employee.getPeriod().setEndDate(endDate);
    em.getTransaction().commit();
}
Run Code Online (Sandbox Code Playgroud)

Nay*_*kar 46

在您的第一个示例中,数据更改在遇到刷新后反映在数据库中,但仍处于事务中.

但在第二个示例中,您将立即提交事务.因此,对数据库进行更改并且事务也在那里结束.

有时,flush可能有用于在正在进行的事务之间保留数据,然后最终提交更改.因此,如果之后出现问题,您也可以回滚以前的更改,例如批量插入/更新.

  • 在第一个示例中没有事务,因此flush()抛出异常. (9认同)
  • @DataNucleus 我认为在 CMT 中,我们不必手动开始/结束事务。 (2认同)
  • 当然,他是否在CMT?在他的另一个例子中,他开始了txn,所以这是我能做的唯一假设 (2认同)
  • @TheProgrammer 不,更改会立即反映在刷新上,请参阅文档 - https://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#flush() & 这里有一些关于它的解释 - http ://stackoverflow.com/a/17703822 (2认同)

Dat*_*eus 15

你确实读过了刷新和提交的javadoc并且知道flush只是一个事务中使用吗?它刷新(但不提交),而commit提交数据(显然).他们是独特的; 没有"偏好".第一个例子是错误的,并且应该在调用flush时产生异常(TransactionRequiredException)

  • 是的确实会提交数据(如前所述),为此,如果尚未将数据刷新到数据存储区,则执行刷新.flush()只是让你可以选择把它放在那里. (7认同)
  • flush()的一个用例是强制生成可在同一事务中使用的ID.例如,当您要创建日志(在数据库中)或历史条目(基本上是副本)时.不使用这些条目与实际实体之间关系的原因是在这种情况下您不必费心使用ID是因为您无法删除实体而不会因外键而丢失日志/历史记录条目. (5认同)
  • 好吧,API所说的关于flush()的所有内容都是"将持久化上下文同步到底层数据库",我之前从未使用过它,但我的事务在调用`EntityManager.getTransaction.commit()`时仍将数据放入数据库.我没有调用EntityManager.flush()!因此,即使没有它,我也无法理解flush()的使用. (2认同)

Aha*_*a M 5

您的两个代码示例都不会保留或合并要写入数据库的实体状态。

EntityManager.flush()我认为比较和不合适EnityManager.EntityTransaction.commit()

lush() 必须包含在事务上下文中,除非需要(在极少数情况下),否则您不必显式执行此操作,而 EntityTransaction.commit() 会为您执行此操作。

请参阅此链接在这种情况下是否有必要调用flush()(JPA接口)?

请参阅此链接关于在调用查询之前使用 JPA 进行刷新的问题以使用flush()的场景