1

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

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

谢谢

急诊室

4

2 回答 2

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 为托管实体提供自动状态检测)。
  4. 而你flush的变化......不存在:)

因此,正如您所试验的那样,您的方法目前没有做任何事情。

现在回到问题:

  • 如果要更新托管实体,则不应调用任何方法,JPA 将自动检测任何状态更改并flush及时保留更改
  • 如果你想更新一个分离的实体,你应该使用merge(并返回合并的实例)。

也可以看看

参考

  • JPA 2.0 规范
    • 第 3.1.1 节“EntityManager 接口”
    • 第 3.2 节“实体实例的生命周期”
    • 第 3.2.7 节“分离的实体”
    • 第 3.2.8 节“托管实例”
于 2010-08-28T21:32:30.403 回答
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 提供程序(在这种情况下为休眠)加载了实体,休眠将为您提供实体,并且它在加载时保留实体状态的内部记录加上它持有对它的实体的引用回来。

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

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

merge()简单更新不需要。

此外,您通常不会flush()显式调用。通常最好让hibernate这样做。Hibernate 将在需要时刷新会话,这通常是在事务提交上,因此提交将为您执行刷新。

于 2010-08-28T19:35:04.987 回答