Java JPA/Hibernate是否在不调用persist时保存

Java JPA/Hibernate是否在不调用persist时保存,java,hibernate,jpa,Java,Hibernate,Jpa,正如您所看到的,我没有调用persist,它被注释掉了,因为我先干运行这段代码。然而,事实证明它不是很干燥。在检查数据库时,我看到数据发生了更改(幸运的是它是一个测试数据库) 显然,我对Hibernate/JPA的理解是有缺陷的。调用persist是否总是需要更改数据?如果没有,保存内容时的规则是什么?是的,当刷新(刷新也通过提交完成)完成时,将保存托管实体如果在该实体上检测到任何更改,则称为脏检查 em.getTransaction().begin(); StringData sd = em

正如您所看到的,我没有调用
persist
,它被注释掉了,因为我先干运行这段代码。然而,事实证明它不是很干燥。在检查数据库时,我看到数据发生了更改(幸运的是它是一个测试数据库)

显然,我对Hibernate/JPA的理解是有缺陷的。调用
persist
是否总是需要更改数据?如果没有,保存内容时的规则是什么?

是的,当刷新(刷新也通过提交完成)完成时,将保存托管实体如果在该实体上检测到任何更改,则称为脏检查

em.getTransaction().begin();

StringData sd = em.find(StringData.class, key);
System.out.println("Old value: " + sd.getData());
sd.setData(newValue);
// em.persist(sd);

em.getTransaction().commit();
这行代码从em会话检索StringData实例sd,您所做的任何更改都将保存在flush上(当事务结束时),因为对象实例与em会话关联(ie托管)


您可以分离它,或者从方法返回它。在事务之外,它与em会话没有关联,在通过合并重新连接之前,更改不会被持久化。

接受的答案有点误导。托管实体在刷新时自动保存,但“如果检测到任何更改”,则不会发出刷新。这是一种误导,因为这意味着任何更改都会立即发生刷新

相反,在默认的自动刷新模式下,会在非常特定的条件下触发刷新

StringData sd = em.find(StringData.class, key);
我的观点是,这不是一个立即冲水,而是只有在满足某些条件时才会触发。这是微妙但重要的区别


参考-

很高兴知道。这是可以依赖的,还是
持久化
调用仍然是明智的?@Bart仅以这种方式保存托管实体,托管意味着用于加载这些实体的实体管理器尚未关闭,因此请小心。而persist将创建一个新实体。如果在已经存在的实体(如此处)中使用它,它将引发异常。看看API:但是我一直在加载的实体上使用
persist
,没有例外。@Bart Strange,在persist的API中:“EntityExistsException-如果实体已经存在。(如果实体已存在,则在调用持久化操作时可能会引发EntityExistsException,或者在刷新或提交时可能会引发EntityExistsException或另一个PersistenceException。)@Bart好的,API似乎不是很准确,看看公认的答案:重要的部分不是事务已提交,重要的部分是实体管理器已关闭。如果事务已提交但实体管理器未关闭,则实体仍与实体管理器关联。@Pablo如果实体在事务外部更改,但在实体管理器内更改?@Bart下次刷新()或提交()时,实体管理器将尝试保存它调用。我在回答中并不是指当检测到任何更改时会触发刷新。我只是指当检测到对实体的任何更改时,刷新将保存该实体。我将稍微更改一下回答,以澄清这一点。
Example 1 - If you interleave a native SQL within your transaction.
Example 2 - If you write a JPQL/HQL query that overlaps with cache.
Example 3 - If you exit the transaction normally.