0

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.

2 Answers 2

0

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

Sign up to request clarification or add additional context in comments.

1 Comment

+1 didn't know there is a difference between field and method annotation functionality. Can you provide some citations about field/method annotation impact on lazy initialization (I would gladly accept the answer)?
0

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.