我正在尝试在Spring MVC中设置OpenSessionInViewInterceptor以修复:org.hibernate.LazyInitializationException:无法初始化代理- 没有会话。
以下是我已经拥有的代码以及错误的来源。
AppConfig.java
@Configuration @PropertySource("classpath:db.properties") @EnableTransactionManagement @ComponentScans(value = { @ComponentScan("com.debugger.spring.web.tests"), @ComponentScan("com.debugger.spring.web.service"), @ComponentScan("com.debugger.spring.web.dao"), @ComponentScan("com.debugger.spring.web.controllers") }) public class AppConfig implements WebMvcConfigurer { @Autowired private Environment env; @Bean public LocalSessionFactoryBean getSessionFactory() { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); Properties props = new Properties(); // Setting JDBC properties ... // Setting Hibernate properties ... // Setting C3P0 properties ... return factoryBean; } @Bean public OpenSessionInViewInterceptor openSessionInViewInterceptor() { OpenSessionInViewInterceptor openSessionInViewInterceptor = new OpenSessionInViewInterceptor(); openSessionInViewInterceptor.setSessionFactory(getSessionFactory().getObject()); return openSessionInViewInterceptor; } }
Featured.jsp
<c:choose> <c:when test='${article.user.isSubscribed() and article.user.subscription.type eq "silver" }'> <a class="bold" href='${pageContext.request.contextPath}/u/${article.user.username}'><span class="silvername"> <c:out value="${article.user.name}"></c:out></span></a> </c:when> <c:when test='${article.user.isSubscribed() and article.user.subscription.type eq "gold" }'> <a class="bold" href='${pageContext.request.contextPath}/u/${article.user.username}'><span class="goldname"> <c:out value="${article.user.name}"></c:out></span></a> </c:when> <c:when test='${article.user.isSubscribed() and article.user.subscription.type eq "premium" }'> <a class="bold" href='${pageContext.request.contextPath}/u/${article.user.username}'><span class="premiumname"> <c:out value="${article.user.name}"></c:out></span></a> </c:when> <c:otherwise> <a class="bold" href='${pageContext.request.contextPath}/u/${article.user.username}'><span> <c:out value="${article.user.name}"></c:out> </span></a> </c:otherwise> </c:choose>
$ {article.user.isSubscribed()}最有可能引发错误,因为无法提取用户。我希望它能在不使用急切获取的情况下运行,并且我认为可以通过正确设置OpenSessionInViewInterceptor来实现它。
在配置类中重写WebMvcConfigurer#addInterceptors(InterceptorRegistry):
@Override public void addInterceptors(InterceptorRegistry registry) { OpenSessionInViewInterceptor openSessionInViewInterceptor = new OpenSessionInViewInterceptor(); openSessionInViewInterceptor.setSessionFactory(getSessionFactory().getObject()); registry.addWebRequestInterceptor(openSessionInViewInterceptor).addPathPatterns("/**"); }
还要添加@EnableWebMvcconfig类。
@EnableWebMvc
针对OP的评论:
我不确定为什么它不起作用。在我看来一切都很好。还有另一种方法可以实现此目的:
设置hibernate.enable_lazy_load_no_trans属性true。
hibernate.enable_lazy_load_no_trans
true
见 23.9.1。 有关更多信息,请参见《 Hibernate用户指南》中的“ 获取属性 ”。
但是,如指南中所述,这 不是 一个很好的选择:
尽管启用此配置可以 LazyInitializationException取消,但最好使用获取计划,该计划可确保在关闭会话之前正确初始化所有属性。 In reality, you shouldn’t probably enable this setting anyway.
尽管启用此配置可以 LazyInitializationException取消,但最好使用获取计划,该计划可确保在关闭会话之前正确初始化所有属性。
LazyInitializationException
In reality, you shouldn’t probably enable this setting anyway.