【问题标题】:How does an entity get an ID before a transaction is committed in JPA/Play?在 JPA/Play 中提交事务之前,实体如何获取 ID?
【发布时间】:2011-12-31 11:06:12
【问题描述】:

See this question.

事实证明,即使没有手动提交事务,在提交TX之前,调用save()方法后,人还是有一个ID。

数据库不负责分配 ID 字段吗?如果是这样,如何在提交之前填写 ID 字段?在提交 TX 之前是否与 DB 发生任何通信?

【问题讨论】:

    标签: java jpa playframework


    【解决方案1】:

    是的,JPA 允许在事务提交之前与数据库通信。它可能发生,即当您显式调用 EntityManager#flush()

    此外,JPA 提供程序可以在认为有必要时执行刷新操作。但是,为了方便起见,JPA 提供者将 DB 操作延迟到提交事务的时间。

    一些自动 ID 生成器策略必须访问数据库才能获得 PK 值(据我所知,IDENTITY 策略就是这样工作的)。
    相反,TABLESEQUENCE 生成器不需要访问数据库来获取 ID 值。他们使用 allocationSize 参数向 DB TABLE 或 SEQUENCE 询问将提供给新实体的 batch ID,而无需与数据库进一步通信。

    【讨论】:

    • 一些自动 ID 生成器策略必须命中数据库才能获取 PK 值——这是否意味着只要调用 session.save 而不是在提交事务后保存记录?
    【解决方案2】:

    玩!每次使用模型上的 save() 方法保存对象时,都会刷新持久性上下文(将更改写入数据库并允许它获取生成的 ID):

    来自 JPABase._save() 源代码:

    if (!em().contains(this)) {
        em().persist(this);
        PlayPlugin.postEvent("JPASupport.objectPersisted", this);
    }
    // ...
    try {
        em().flush();
    } catch (PersistenceException e) {
        // ...
    }
    

    【讨论】:

      【解决方案3】:

      据我所知,在对象持久化之前,我们无法获取对象的 ID(假设它是自动编号的)。 而且我个人认为分配一些应该由RDBMS在它之外完成的事情是非常危险的。

      【讨论】:

      • 为什么? JPA 会处理它......如果在您提交事务时该 ID 不可用,它就会失败......只要您知道事务可能会失败(出于多种原因),我觉得早点用ID是可以的。
      【解决方案4】:

      begintransaction 和 commit 之间,调用 save 或 update 方法后,你应该使用:

      EntityManagerHelper.getEntityManager().flush();
      

      如果你不调用它,Object 将会丢失并且无法保存到 DB。

      所以在调用它之后,你会在对象中获取它的 id。

      【讨论】:

        猜你喜欢
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多