【问题标题】:JPA - saving changes without persist() invokedJPA - 在没有调用 persist() 的情况下保存更改
【发布时间】:2021-01-06 07:43:57
【问题描述】:

我们正在使用 JPA + Spring + EJB 的 Toplink 实现。在我们的一个 EJB 中,我们有这样的东西:

public void updateUser(long userId, String newName){
    User u = em.get(User.class, userId);
    u.setName(newName);
    // no persist is invoked here
}

所以,基本上这个updateUser() 方法应该使用给定的userId 更新用户的名称。 但是这个方法的作者忘记调用em.persist(u)了。

最奇怪的是它运行良好。怎么会这样?我百分百确定 如果不调用em.persist()em.merge(),就无法将更改保存到数据库中。他们可以吗?有没有可能发生这种情况的情况?

【问题讨论】:

    标签: jpa toplink-essentials persist


    【解决方案1】:

    您正在使用托管实体。如果实体由于其实体管理器关闭而没有分离,则在刷新/关闭会话并提交事务时,对实体所做的所有更改都会反映到数据库中。

    来自Java EE tutorial

    持久实体的状态是 同步到数据库的时候 与该实体进行的交易 相关的提交。

    为了清晰和解释而编辑:因此,实体在其生命周期中可能处于三种不同的模式:

    • 未保存:实体已实例化,但尚未调用 persist()
    • 托管:实体已使用persist() 持久化,或从数据库加载,并与实体管理器会话相关联。刷新实体管理器会话时,对实体的所有更改都会反映到数据库中。
    • 已分离:实体的实体管理器会话已关闭。对实体的更改不会自动反映到数据库中,但可以使用merge() 命令显式合并。

    【讨论】:

    • 谢谢。这有很大帮助!我一直认为调用 em.persist() 是必需的,即使对象与当前的 EntityManager 相关联。
    • 奇怪:在我的设置中,我引用了一个托管实体。然后我改变这个实体的状态。然后我打电话给entityManager.flush()。如果这是在事务中运行,则实体的更改状态被写入到数据库。如果这是在没有事务的情况下运行,则实体的更改状态不会写入到数据库。那么下面的陈述是真的吗?:“为了将obj 的最新状态写入数据库,总是必须有一个事务提交或一个entityManager.persist(obj) 调用。”....(我正在使用 JPA 2.0 和 Hibernate (4.1.7.Final))
    • @Abdull,是的,JPA 规范没有定义任何自动提交行为,所以你需要一个正在进行的事务,否则根本没有任何东西写入数据库。
    • @Henning,好的,谢谢!目前,您的回答是:“[...] 当刷新实体管理器会话时,对实体的所有更改都会反映到数据库中。”......重写它怎么样: “[...] 如果有一个正在进行的事务,当实体管理器会话被刷新时,对实体的所有更改都会反映到数据库中。” ....(或者还有更多的微妙之处参与?)
    • @Abdull,它确实说“当会话被刷新/关闭时事务提交”,所以我认为我们已经涵盖了事务部分,对吧?
    猜你喜欢
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2017-08-08
    • 1970-01-01
    相关资源
    最近更新 更多