user4413257
user4413257

Reputation:

How to work with lazy initialization? [LazyInitializationException]

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

Answers (2)

user4413257
user4413257

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

Christian Beikov
Christian Beikov

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

Related Questions