Justas Justas - 3 months ago 16
Java Question

Hibernate does not refresh entity childs completely

I use Hibernate 5.1.0.Final. My

GenericDAO
class main methods:

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;
}


I have
Item
entity which contains
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;

}


First, I load
Item
with
genericDAO.find(id)
method - it contains up-to-date list of images. Then I load
Item
with the same ID in another REST method which removes old images and adds new ones, changes title. Later, if try to reload
Item
with
genericDAO.find(id)
in the first REST method, I get outdated images - they aren't selected again while
Item
title is retrieved correctly.

How to get completely refreshed entity with its childs from a database?

Answer

Your way of caching your entityManagers is correct since in the request scope but it has side-effects as you can notice.
You use the level one cache of Hibernate.
Why don't use a distinct entityManager instance by transaction ?
It should not be expensive to instantiate a EntityManager by user request.

If you want to cache the entityManager, entityManager.refres‌​h(e) seems not enough since it doesn't seem to clear the level one cache. So, if you want to clear the first level cache, you should try to clear the persistenceContext. No guarantee but you can try : entityManager.clear()

Personally, I prefer the solution using a unique entityManager instance by transaction. It's cheap and a clear design.

Comments