【发布时间】:2011-12-31 11:06:12
【问题描述】:
事实证明,即使没有手动提交事务,在提交TX之前,调用save()方法后,人还是有一个ID。
数据库不负责分配 ID 字段吗?如果是这样,如何在提交之前填写 ID 字段?在提交 TX 之前是否与 DB 发生任何通信?
【问题讨论】:
标签: java jpa playframework
事实证明,即使没有手动提交事务,在提交TX之前,调用save()方法后,人还是有一个ID。
数据库不负责分配 ID 字段吗?如果是这样,如何在提交之前填写 ID 字段?在提交 TX 之前是否与 DB 发生任何通信?
【问题讨论】:
标签: java jpa playframework
是的,JPA 允许在事务提交之前与数据库通信。它可能发生,即当您显式调用 EntityManager#flush()。
此外,JPA 提供程序可以在认为有必要时执行刷新操作。但是,为了方便起见,JPA 提供者将 DB 操作延迟到提交事务的时间。
一些自动 ID 生成器策略必须访问数据库才能获得 PK 值(据我所知,IDENTITY 策略就是这样工作的)。
相反,TABLE 或SEQUENCE 生成器不需要访问数据库来获取 ID 值。他们使用 allocationSize 参数向 DB TABLE 或 SEQUENCE 询问将提供给新实体的 batch ID,而无需与数据库进一步通信。
【讨论】:
玩!每次使用模型上的 save() 方法保存对象时,都会刷新持久性上下文(将更改写入数据库并允许它获取生成的 ID):
来自 JPABase._save() 源代码:
if (!em().contains(this)) {
em().persist(this);
PlayPlugin.postEvent("JPASupport.objectPersisted", this);
}
// ...
try {
em().flush();
} catch (PersistenceException e) {
// ...
}
【讨论】:
据我所知,在对象持久化之前,我们无法获取对象的 ID(假设它是自动编号的)。 而且我个人认为分配一些应该由RDBMS在它之外完成的事情是非常危险的。
【讨论】:
begintransaction 和 commit 之间,调用 save 或 update 方法后,你应该使用:
EntityManagerHelper.getEntityManager().flush();
如果你不调用它,Object 将会丢失并且无法保存到 DB。
所以在调用它之后,你会在对象中获取它的 id。
【讨论】: