【问题标题】:Hibernate session.persist() vs JPA entityManager.persist()休眠 session.persist() 与 JPA entityManager.persist()
【发布时间】:2014-07-07 18:29:06
【问题描述】:

来自 Java Persistence with Hibernate(Manning,2007)p。 419:

我应该在 Session 上使用 persist() 吗? Hibernate Session 接口 还具有一个 persist() 方法。它具有与 JPA 的 persist() 操作。但是,有一个重要的区别 关于冲洗的两个操作之间。中 同步,Hibernate Session 不会级联persist() 对关联实体和集合的操作,即使您已映射 与此选项的关联。 它只级联到实体 调用 persist() 时可以访问! 只有 save()(和 update())是 如果您使用 Session API,则在刷新时级联。在 JPA 中 应用程序,然而,它是相反的:只有persist()是 在刷新时级联。

如此难以辨认的措辞...“调用persist() 时可访问的实体”是什么意思?

如果我更新了关联实体,那么它应该不是“可访问的”吗?

还有……如果是session.persist()行为的一部分,那为什么不在javadoc中呢?

【问题讨论】:

  • reachable = 您可以从传递的对象导航到持久化以到达另一个对象。此导航是通过普通的 java 对象字段进行的。可达也意味着从对象 A 导航到对象 B 到对象 C 等。

标签: hibernate jpa


【解决方案1】:

Hibernate 的 EntityManager 实现是:

org\hibernate\hibernate-entitymanager\4.3.5.Final\hibernate-entitymanager-4.3.5.Final-sources.jar!\org\hibernate\jpa\spi\AbstractEntityManagerImpl.java

这是persist()方法

@Override
public void persist(Object entity) {
    checkOpen();
    try {
        internalGetSession().persist( entity );
    }
    catch ( MappingException e ) {
        throw convert( new IllegalArgumentException( e.getMessage() ) ) ;
    }
    catch ( RuntimeException e ) {
        throw convert( e );
    }
}

所以 JPA persist(entity) 实际上是在调用 org.hibernate.internal.Session.persist(entity)。

因此,在持久化实体方面,JPA 和 Hibernate 之间应该没有任何区别。

它仅级联到您调用时可访问的实体 坚持()!

2007 年 Hibernate 3.2 已经发布,3.3 版本即将发布。那时JPA was only a draft:

您也可以使用persist() 代替save(),其语义在EJB3 >> > 早期草案中定义。

但根据文档:

如果将父级传递给persist(),则将所有子级传递给 坚持()

对于 JPA,级联 persist() 是有意义的,因为根本没有 save() 操作。但当时人们使用的是 save()、saveOrUpadet() 甚至 saveOrUpdateCopy(),它们已被弃用,取而代之的是 persist() 和 merge()。

当时,persist JPA 定义只是一个草稿,因此特定的实现并没有反映明确的特性。

【讨论】:

  • 您是说“[Hibernate] 仅级联到 [与 cascade="persist" 映射并且] 在您调用 persist() 时可以访问的实体”在当前版本的 Hibernate 中不再适用?而且,如果在某个时候这实际上是 Hibernate 的行为,它是如何实现的(请参阅我对 JB Nizet 的评论)?
  • 这不是我要说的。我是说 jpa 和 hibernate 在持久化方面应该没有任何区别。
  • 为什么不暗示我所说的?您说“对于 JPA,级联persist() 是有意义的”[即使在flush() 时间可访问的子实体虽然在调用persist() 时无法访问]....所以这意味着Hibernate 现在的行为相同。 ..
【解决方案2】:

我真的不知道这是不是真的,但我至少可以解释它的含义。

假设您有以下实体:

public class Order {
    @OneToMany(cascade = PERSIST)
    private List<OrderLine> lines;
    // ...
}

然后您执行以下操作:

Order order = new Order();
session.persist(order);
OrderLine line = new OrderLine();
order.addLine(line);
session.flush(); // the flush could also be called implicitely, when committing or executing a query

根据您问题中的文字,该行不会被持久化,因为它在调用persist(order)时无法从顺序到达:此时,该行还没有按顺序。

另一方面,你是否使用实体管理器:

Order order = new Order();
em.persist(order);
OrderLine line = new OrderLine();
order.addLine(line);
em.flush(); // the flush could also be called implicitely, when committing or executing a query

然后该行将被持久化,因为它可以在刷新时从订单访问,此时实体的状态已同步到数据库。

【讨论】:

  • 您的意思是order.addLine(line)?我想你是说这在理论上是他们可能的意思,但你不知道他们是否真的这样做?您所描述的这种情况需要每个持久对象有多个快照...... Hibernate 真的会过度杀伤吗?
  • 是的,对不起,我的意思是order.addLine()。我不明白“每个持久对象多个快照”是什么意思。每个会话对于每个给定的持久对象都有一个且只有一个实例。
猜你喜欢
  • 2021-06-25
  • 2019-02-23
  • 2011-12-11
  • 1970-01-01
  • 2016-01-19
  • 2013-06-19
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多