从@modelAttribute获取对象后,如何不实例化调用Fetch.Lazy列表?
解决Lazy List调用异常的方案
提前初始化Lazy集合:在Service层(处于事务/持久化上下文内)调用集合的
size()方法,或者用ORM框架的初始化工具(比如Hibernate的Hibernate.initialize()),提前加载集合数据。这样@ModelAttribute拿到的对象里集合已经是初始化完成的,后续调用不会触发异常。
示例代码:// 带@Transactional的Service方法 public YourEntity getInitializedEntity(Long id) { YourEntity entity = entityManager.find(YourEntity.class, id); // 触发lazy集合加载 Hibernate.initialize(entity.getLazyList()); // 或者调用集合方法触发加载 entity.getLazyList().size(); return entity; }修改Fetch策略为Eager:如果业务场景下这个集合每次都需要被访问,可以直接在实体类的集合字段上,将
fetch = FetchType.LAZY改为FetchType.EAGER,这样查询实体时会自动加载关联集合。注意这种方式可能带来性能损耗,按需使用。
示例代码:@OneToMany(fetch = FetchType.EAGER) private List<ChildEntity> lazyList;配置Open Session In View(OSIV):通过Spring的OSIV过滤器,让持久化会话在视图渲染阶段保持打开,这样即使在Controller层调用lazy集合也能完成初始化。但该方式可能导致会话长时间占用,存在性能和事务风险,谨慎使用。
配置示例(web.xml):<filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>重新关联对象到持久化上下文:如果@ModelAttribute中的对象已经处于脱离上下文的状态,可以在Service或Controller层将对象merge回会话,再调用集合。
示例代码:YourEntity mergedEntity = entityManager.merge(modelAttributeEntity); // 触发集合加载 mergedEntity.getLazyList().forEach(item -> {});
内容的提问来源于stack exchange,提问作者PereZix
相关产品推荐
相关产品推荐

