如何使OpenSessionInViewInterceptor在Spring MVC中工作

时间:2018-12-21 17:10:33

标签: hibernate spring-mvc interceptor

我正在尝试在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来实现它。

1 个答案:

答案 0 :(得分:1)

在您的配置类中覆盖WebMvcConfigurer#addInterceptors(InterceptorRegistry)

@Override
public void addInterceptors(InterceptorRegistry registry) {
    OpenSessionInViewInterceptor openSessionInViewInterceptor = new OpenSessionInViewInterceptor();
    openSessionInViewInterceptor.setSessionFactory(getSessionFactory().getObject());

    registry.addWebRequestInterceptor(openSessionInViewInterceptor).addPathPatterns("/**");
}

还要在配置类上添加@EnableWebMvc

针对OP的评论:

我不确定为什么它不起作用。在我看来一切都很好。还有另一种方法可以实现:

设置hibernate.enable_lazy_load_no_trans属性true

有关更多信息,请参见23.9.1. Fetching properties in Hibernate User Guide

但这不是 指南中所述的一个很好的选择:

  

尽管启用此配置可​​以使   LazyInitializationException消失了,最好使用提取计划   保证所有属性都在之前正确初始化   该会话已关闭。

In reality, you shouldn’t probably enable this setting anyway.