如何在Hibernate JPA2中实现“更新”

时间:2010-08-28 19:10:06

标签: hibernate orm jpa jpa-2.0

有人可以提供一个演示如何实现简单“更新”方法的简单示例吗?这个没有更新

@Override
public void update(final BS bs) {
    BS fullBs = em.find(BS.class, bs.getId());
    BS merged = this.em.merge(fullBs);
    this.em.flush();
}

由于

ER

2 个答案:

答案 0 :(得分:2)

  

有人可以提供一个演示如何实现简单“更新”方法的简单示例吗?这个没有更新(...)

嗯,这实际上取决于您想要更新的实体的状态(托管与分离),但您的代码肯定是无用的。他们分析它:

1. public void update(final BS bs) {
2.     BS fullBs = em.find(BS.class, bs.getId());
3.     BS merged = this.em.merge(fullBs);
4.     this.em.flush();
5. }
  1. 正如我所说,作为参数传递的bs实体的状态不清楚。总之...
  2. 然后,您使用其Id将托管实体加载到fullBs,然后...... 不要更改任何内容
  3. 然后您尝试merge一个完全没有必要的已管理实体(JPA为托管实体提供automatic state detection。)
  4. flush变化......不存在:)
  5. 因此,正如您进行实验一样,您的方法目前没有做任何事情。

    现在回到问题:

    • 如果您要更新托管实体,则不应调用任何方法,JPA会自动检测任何状态更改并在flush时间保持更改
    • 如果要更新分离的实体,则应使用merge(并返回合并的实例)。

    另见

    参考

    • JPA 2.0规范
      • 第3.1.1节“EntityManager接口”
      • 第3.2节“实体实例的生命周期”
      • 第3.2.7节“独立实体”
      • 第3.2.8节“托管实例”

答案 1 :(得分:1)

使用脏检查而不是显式更新调用来实现hibernate中的更新。例如,在上面的方法中,如果您find()您的BS实体然后修改属性然后调用flush(),您将看到正在生成SQL更新。没有修改flush()将决定无所事事。

实施例

@Override
public void update(final BS bs) {
    BS fullBs = em.find(BS.class, bs.getId());
    fullBs.setMyProperty("hello");
    this.em.flush();
}

执行find()实体由JPA提供程序加载(在本例中为hibernate),hibernate将为您提供实体,并在加载时保留实体状态的内部记录PLUS它持有对它返回的实体的引用。

然后当调用flush()时,hibernate dirty会检查其缓存中的每个实体(称为第一级缓存或会话缓存)。脏检查包括检查使用内部状态记录获得的实体的每个属性。如果存在任何差异,则实体为“脏”,并且将生成SQL更新。

请注意,flush()不是事务提交。它只是说,“请保持会话中对数据库所做的任何更改”,这将涉及插入/更新/删除语句。

简单更新不需要merge()

此外,您通常不会明确地致电flush()。让hibernate这样做通常会更好。 Hibernate将在需要时刷新会话,通常是在事务提交时,因此提交将为您执行刷新。