【问题标题】:Hibernate does not refresh entity childs completelyHibernate 不会完全刷新实体子项
【发布时间】:2016-12-22 19:55:25
【问题描述】:

我使用 Hibernate 5.1.0.Final。我的GenericDAO类主要方法:

public T save(T entity) {
    entityManager.getTransaction().begin();
    entityManager.persist(entity);
    entityManager.getTransaction().commit();
}

public T find(Long entityId) {
    T e = (T) entityManager.find(type, entityId);
    entityManager.refresh(e);
    return e;
}

我有 Item 实体,其中包含 List<Image> images

@Entity
@Table(name="item")
public class Item extends GenericEntity {

    @Column(name="title")
    String title;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "item", cascade = {CascadeType.ALL}, orphanRemoval = true)
    @NotFound(action = NotFoundAction.IGNORE)
    List<Image> images;

    @Version
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="version")
    Date version;

}


@Entity 
@Table(name="image")
public class Image extends GenericEntity {

    @ManyToOne
    @JoinColumn(name="item")
    Item item;

    @Column(name="image_name")
    String imageName;

}

首先,我使用genericDAO.find(id) 方法加载Item - 它包含最新的图像列表。然后我在另一个 REST 方法中加载具有相同 ID 的 Item,该方法删除旧图像并添加新图像,更改标题。稍后,如果尝试在第一个 REST 方法中使用 genericDAO.find(id) 重新加载 Item,我会得到过时的图像 - 在正确检索 Item 标题时不会再次选择它们。

如何从数据库中获取完全刷新的实体及其子实体?

【问题讨论】:

  • 您确定要更新images 字段吗?
  • 是的,如果我直接从数据库查询,更改是可见的。
  • 所以你在某处使用缓存。你在 Hibernate 中使用 2 级缓存吗?或者您的应用程序中的任何缓存机制?
  • 我的 Hibernate 属性包含:properties.put("hibernate.cache.use.query_cache", "false"); properties.put("hibernate.cache.use_second_level_cache", "false");我也希望 entityManager.refresh(e);应该得到最新的数据。
  • 确实应该。你对这两个电话使用相同的会话吗?如果相同,问题就在那里。您可以通过会话检查它。对象的evict()

标签: java hibernate rest jpa entitymanager


【解决方案1】:

您缓存entityManagers 的方式是正确的,因为在request 范围内,但您可以注意到它有副作用。
你使用 Hibernate 的一级缓存。
为什么不通过事务使用不同的 entityManager 实例?
通过用户请求实例化 EntityManager 应该不会很昂贵。

如果要缓存 entityManager,entityManager.refres‌​h(e) 似乎还不够,因为它似乎没有清除一级缓存。所以,如果你想清除一级缓存,你应该尝试清除persistenceContext。不能保证,但你可以试试:entityManager.clear()

就个人而言,我更喜欢通过事务使用唯一entityManager 实例的解决方案。它便宜且设计清晰。

【讨论】:

  • entityManager.clear();在将其注入 DAO 之前解决了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 2020-11-07
  • 2011-07-01
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多