Reputation:
To fetch lazy object, you need to invoke Hibernate.initialize(proxy)
e.g. in your service class:
public <R> R fetchLazy(T entity, Function<T,R> proxyMapper) {
entity = ensureEntityHasOpenedSession(entity);
R proxy = proxyMapper.apply(entity);
Hibernate.initialize(proxy);
return proxy;
}
Outside of the service scope one would need to call:
AnotherEntity another = service.fetchLazy(entity, Entity::getAnotherEntity);
Now, the question is why this works:
another.getId();
while subsequent call does not:
entity.getAnotherEntity().getId(); // LazyInitializationException
Has not been AnotherEntity
stored in Entity
after first fetch? Do I always need to call
service.fetchLazy(entity, Entity::getAnotherEntity).getSomething();
If so, does Hibernate.initialize(Object)
return cached proxy at second call or there is always another database access (query execution)?
EDIT
I'm using JPA annotations on private class fields in combination with lombok's @Getter @Setter annotations.
Upvotes: 0
Views: 345
Reputation:
The problem with subsequent call was implementation of ensureEntityHasOpenedSession(entity)
method in combination with access strategy as pointed by @ChristianBeikov.
To be more specific, I have implemented mentioned method as entityManager.find(entityClass, entityId)
which returns new instance of the entity. As a result, AnotherEntity
proxy was initialized in new entity instance, while subsequent call was manipulating with old entity instance. Since I was using field annotations, any method call has led to proxy initialization as stated in JPA implementation patterns: Field access vs. property access:
Hibernate’s lazy loading implementation always initializes a lazy proxy when any method on that proxy is invoked. The only exception to this is the method annotated with the @Id annotation when you use property access. But when you use field access there is no such method and Hibernate initializes the proxy even when invoking the method that returns the identity of the entity.
hence LazyInitializationException
(old entity with closed session + trying to initialize proxy).
Upvotes: 0
Reputation: 16400
You are probably using JPA field access i.e. you annotated the Java fields of your entity classes rather than the getters. This is a known limitation of field access in Hibernate. The only way to avoid the exception or explicit initialization is by using property access instead.
Also see the following JIRA issues for further information
Upvotes: 0