如何使用惰性初始化? [延迟初始化异常]
How to work with lazy initialization? [LazyInitializationException]
要获取惰性对象,您需要调用 Hibernate.initialize(proxy)
例如为您服务class:
public <R> R fetchLazy(T entity, Function<T,R> proxyMapper) {
entity = ensureEntityHasOpenedSession(entity);
R proxy = proxyMapper.apply(entity);
Hibernate.initialize(proxy);
return proxy;
}
在服务范围之外需要调用:
AnotherEntity another = service.fetchLazy(entity, Entity::getAnotherEntity);
现在,问题是为什么会这样:
another.getId();
而后续调用不会:
entity.getAnotherEntity().getId(); // LazyInitializationException
第一次获取后没有AnotherEntity
存储在Entity
中?我总是需要打电话给
service.fetchLazy(entity, Entity::getAnotherEntity).getSomething();
如果是这样,Hibernate.initialize(Object)
return 是否在第二次调用时缓存了代理,或者总是有另一个数据库访问(查询执行)?
编辑
您可能正在使用 JPA 字段访问,即您注释了实体 类 的 Java 字段而不是 getter。这是 Hibernate 中字段访问的已知限制。避免异常或显式初始化的唯一方法是使用 属性 访问。
另请参阅以下 JIRA 问题以获取更多信息
后续调用的问题是 ensureEntityHasOpenedSession(entity)
方法结合 access strategy 的实现,正如@ChristianBeikov 所指出的。
更具体地说,我已经将提到的方法实现为 entityManager.find(entityClass, entityId)
,其中 returns 实体的新实例 。结果,AnotherEntity
代理在新实体实例中被初始化,而后续调用是使用旧实体实例进行操作。由于我使用的是 字段注释 ,任何方法调用都会导致代理初始化,如 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.
因此 LazyInitializationException
(关闭会话的旧实体 + 尝试初始化代理)。
要获取惰性对象,您需要调用 Hibernate.initialize(proxy)
例如为您服务class:
public <R> R fetchLazy(T entity, Function<T,R> proxyMapper) {
entity = ensureEntityHasOpenedSession(entity);
R proxy = proxyMapper.apply(entity);
Hibernate.initialize(proxy);
return proxy;
}
在服务范围之外需要调用:
AnotherEntity another = service.fetchLazy(entity, Entity::getAnotherEntity);
现在,问题是为什么会这样:
another.getId();
而后续调用不会:
entity.getAnotherEntity().getId(); // LazyInitializationException
第一次获取后没有AnotherEntity
存储在Entity
中?我总是需要打电话给
service.fetchLazy(entity, Entity::getAnotherEntity).getSomething();
如果是这样,Hibernate.initialize(Object)
return 是否在第二次调用时缓存了代理,或者总是有另一个数据库访问(查询执行)?
编辑
您可能正在使用 JPA 字段访问,即您注释了实体 类 的 Java 字段而不是 getter。这是 Hibernate 中字段访问的已知限制。避免异常或显式初始化的唯一方法是使用 属性 访问。
另请参阅以下 JIRA 问题以获取更多信息
后续调用的问题是 ensureEntityHasOpenedSession(entity)
方法结合 access strategy 的实现,正如@ChristianBeikov 所指出的。
更具体地说,我已经将提到的方法实现为 entityManager.find(entityClass, entityId)
,其中 returns 实体的新实例 。结果,AnotherEntity
代理在新实体实例中被初始化,而后续调用是使用旧实体实例进行操作。由于我使用的是 字段注释 ,任何方法调用都会导致代理初始化,如 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.
因此 LazyInitializationException
(关闭会话的旧实体 + 尝试初始化代理)。