user2578525
user2578525

Reputation: 191

JPA - EntityGraph and Hibernate L2 Cache (ehcache)

I have a one-to-many relationship defined as below

@Cacheable
@Entity
@NamedEntityGraph(
    name = "Parent.Child",
    attributeNodes = {
        @NamedAttributeNode("children"),
    }
)
public class Parent {
    private Set<Child> children;
    // getter - setter
}

Now in my DAL, i'm calling this method

@Override
    public Parent getParentWithChildren(int id) {
        EntityGraph<?> graph = entityManager.getEntityGraph("Parent.Child");
        Map<String, Object> props = new HashMap<>();
        props.put("javax.persistence.fetchgraph", graph);
        return entityManager.find(Parent.class, id, props);
    }

Since i have loaded Parent with Children, i should be able to use children collection outside of the transaction. But i'm getting Lazyinitialization Exception. This happens only when hibernate level 2 cache - ehcache is enabled. If i disable it from config, it works as expected. Also if i initialize collection explicitly after find, it works as expected. So is it a bug?. I'm using Hibernate 5.2.6.Final with JPA 2.1.

EDIT: One more thing i noticed was that entity loads fine for the first time, so that problem must be related with hibernate & cache provider.

Upvotes: 2

Views: 891

Answers (2)

gogo
gogo

Reputation: 1011

In order for Hibernate to use an entity graph one must bypass the second-level cache (e.g. EhCache) by using the javax.persistence.cache.retrieveMode hint with the value CacheRetrieveMode.BYPASS:

final EntityGraph<?> graph = em.getEntityGraph("myGraph");
final Map<String, Object> hints = new HashMap<>();
hints.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
hints.put("javax.persistence.fetchgraph", graph);
final SomeEntity entity = em.find(SomeEntity.class, 42, hints);

Note that the second-level cache will still be populated as usual.

Upvotes: 1

Henri
Henri

Reputation: 5711

No. It's not a bug. I guess Hibernate is delaying the loading from cache until really necessary. The implementation can decide to be lazy as see fit unless you ask for eager fetching.

So the general rule is to load everything you need before going out of the transaction (before closing the Hibernate session to be precise).

Upvotes: 0

Related Questions