java Hibernate不会完全刷新查尔兹

9lowa7mx  于 2023-03-16  发布在  Java
关注(0)|答案(2)|浏览(112)

我使用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;
}

我有一个包含List<Image> imagesItem实体。

@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标题检索正确。
如何从数据库中获得完全刷新的实体及其查尔兹实体?

bq3bfh9z

bq3bfh9z1#

您缓存entityManagers的方式是正确的,因为在request作用域中,但是您可以注意到它有副作用。
使用Hibernate的一级缓存。
为什么不按事务使用不同的entityManager示例?
通过用户请求示例化EntityManager应该不会太昂贵。
如果你想缓存entityManager,entityManager.refres‌​h(e)似乎不够,因为它似乎没有清除一级缓存。所以,如果你想清除一级缓存,你应该尝试清除persistenceContext。不保证,但你可以尝试:entityManager.clear()
就我个人而言,我更喜欢使用独特的entityManager事务示例的解决方案,它便宜而且设计清晰。

2ul0zpep

2ul0zpep2#

当数据库同时发生更改时,Hibernate的一级/二级缓存与可见性无关。您需要查看隔离级别,REPEATABLE_READ是最常见的,应该是您的问题来源。
您可以“锁定”实体以防止修改:

@PersistenceContext
private EntityManager em;

@Transactional
@Test
public void lock() {
    final Session session = em.unwrap(Session.class);
    final Book book = session.get(Book.class, 1L, LockMode.PESSIMISTIC_WRITE);
}

根据DB / Hibernate适配器,可能会导致SELECT .... FOR UPDATE

相关问题