使用 Spring Boot 和 Data JPA,尽管有 OpenSessionInViewFilter,但仍会出现 LazyInitializationException

Posted

技术标签:

【中文标题】使用 Spring Boot 和 Data JPA,尽管有 OpenSessionInViewFilter,但仍会出现 LazyInitializationException【英文标题】:Using Spring Boot and Data JPA, getting LazyInitializationException despite the OpenSesionInViewFilter 【发布时间】:2016-08-27 00:45:41 【问题描述】:

我正在使用带有 Spring Boot 的 Tapestry 5,使用这个很棒的小库:https://github.com/code8/tapestry-boot

然而,尽管我使用了 OpenSesionInViewFilter,但我还是得到了臭名昭著的 LazyInitializationException。撇开 OpenSesionInViewFilter 的优缺点不谈,我想在移植一个大型遗留应用程序时让它与 OpenSesionInViewFilter 一起工作。

我的spring boot配置是

@SpringBootApplication
public class Launcher 
    public static void main(String[] args) 
        new SpringApplicationBuilder(Launcher.class)
                .web(true)
                .run(args);
    
    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory() 
        return new HibernateJpaSessionFactoryBean();
    

    @Bean
    public FilterRegistrationBean registerOpenSessionInViewFilterBean() 
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        OpenSessionInViewFilter filter = new OpenSessionInViewFilter();
        registrationBean.setFilter(filter);
        registrationBean.setOrder(5);
        return registrationBean;
    

我已确保在 TapestryFilter 之前加载 OpenSessionInViewFilter,并在启动时通过 spring 的输出验证了这一点。我将 Tapestry-boot 库编辑为 TapestryFilter 上的 setOrder(10)。

我还通过调试验证了 OpenSessionInViewFilter 实际上是在创建会话。

在下面 LIE 的示例堆栈跟踪中,您可以看到正在使用 OpenSessionInViewFilter。

我有 2 个级别的服务层:

Tapestry Pages --> XXManagerImpl (e.g, UserManager) --> JpaRepository

My Manager 服务的注释如下:

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserManagerImpl implements UserManager, Serializable

我的 JpaRepositories 没有使用 @Transactional 或 @Repository 注释(以防万一)。

初始数据访问按预期工作,但是当我尝试访问延迟初始化字段时,我得到了 LIE。

根异常:

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:147) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:260) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68) ~[hibernate-core-5.1.0.Final.jar:5.1.0.Final]
    at org.mypackage.model.submodel.othermodel$$_jvstde5_1.getName(OtherModel$$_jvstde5_1.java) ~[main/:na]
    at $InternalPropertyConduit_97875b5f2687.get(Unknown Source) ~[na:na]
    at org.apache.tapestry5.internal.bindings.PropBinding.get(PropBinding.java:63) ~[tapestry-core-5.4.1.jar:na]

示例堆栈跟踪:

org.apache.tapestry5.ioc.internal.OperationException: Render queue error in Expansion[PropBinding[expansion mypage/Edit(model.othermodel.name)]]: could not initialize proxy - no Session
    at org.apache.tapestry5.ioc.internal.OperationTrackerImpl.logAndRethrow(OperationTrackerImpl.java:186) ~[tapestry-ioc-5.4.1.jar:na]
    at org.apache.tapestry5.ioc.internal.OperationTrackerImpl.run(OperationTrackerImpl.java:62) ~[tapestry-ioc-5.4.1.jar:na]
    at org.apache.tapestry5.ioc.internal.PerThreadOperationTracker.run(PerThreadOperationTracker.java:60) ~[tapestry-ioc-5.4.1.jar:na]
    at org.apache.tapestry5.ioc.internal.RegistryImpl.run(RegistryImpl.java:1254) ~[tapestry-ioc-5.4.1.jar:na]
    at org.apache.tapestry5.internal.services.RequestOperationTracker.handlePageRender(RequestOperationTracker.java:66) ~[tapestry-core-5.4.1.jar:na]
    at $ComponentRequestHandler_94ac265764f4.handlePageRendewn Source) ~[na:na]
    at $ComponentRequestHandler_94ac2657642d.handlePageRender(Unknown Source) ~[na:na]
    at org.apache.tapestry5.internal.services.PageRenderDispatcher.dispatch(PageRenderDispatcher.java:55) ~[tapestry-core-5.4.1.jar:na]
    at $Dispatcher_94ac265764c8.dispatch(Unknown Source) ~[na:na]
    at $Dispatcher_94ac26576473.dispatch(Unknown Source) ~[na:na]
    at org.apache.tapestry5.modules.TapestryModule$RequestHandlerTerminator.service(TapestryModule.java:305) ~[tapestry-core-5.4.1.jar:na]
    at org.apache.tapestry5.internal.services.RequestErrorFilter.service(RequestErrorFilter.java:26) ~[tapestry-core-5.4.1.jar:na]
    at $RequestHandler_94ac265764c7.service(Unknown Source) [na:na]
    at org.apache.tapestry5.modules.TapestryModule$3.service(TapestryModule.java:846) [tapestry-core-5.4.1.jar:na]
    at $RequestHandler_94ac265764c7.service(Unknown Source) [na:na]
    at org.apache.tapestry5.modules.TapestryModule$2.service(TapestryModule.java:836) [tapestry-core-5.4.1.jar:na]
    at $RequestHandler_94ac265764c7.service(Unknown Source) [na:na]
    at org.apache.tapestry5.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:89) [tapestry-core-5.4.1.jar:na]
    at $RequestHandler_94ac265764c7.service(Unknown Source) [na:na]
    at org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:105) [tapestry-core-5.4.1.jar:na]
    at org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:95) [tapestry-core-5.4.1.jar:na]
    at org.apache.tapestry5.ioc.internal.util.ConcurrentBarrier.withRead(ConcurrentBarrier.java:83) [tapestry-ioc-5.4.1.jar:na]
    at org.apache.tapestry5.internal.services.CheckForUpdatesFilter.service(CheckForUpdatesFilter.java:119) [tapestry-core-5.4.1.jar:na]
    at $RequestHandler_94ac265764c7.service(Unknown Source) [na:na]
    at $RequestHandler_94ac2657649d.service(Unknown Source) [na:na]
    at org.apache.tapestry5.modules.TapestryModule$HttpServletRequestHandlerTerminator.service(TapestryModule.java:256) [tapestry-core-5.4.1.jar:na]
    apache.tapestry5.upload.internal.services.MultipartServletRequestFilter.service(MultipartServletRequestFilter.java:45) [tapestry-upload-5.4.1.jar:na]
    at $HttpServletRequestHandler_94ac265764c4.service(Unknown Source) [na:na]
    at org.apache.tapestry5.internal.gzip.GZipFilter.service(GZipFilter.java:59) [tapestry-core-5.4.1.jar:na]
    at $HttpServletRequestHandler_94ac265764c4.service(Unknown Source) [na:na]
    at org.apache.tapestry5.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62) [tapestry-core-5.4.1.jar:na]
    at $HttpServletRequestFilter_94ac2657645a.service(Unknown Source) [na:na]
    at $HttpServletRequestHandler_94ac265764c4.service(Unknown Source) [na:na]
    at org.apache.tapestry5.modules.TapestryModule$1.service(TapestryModule.java:796) [tapestry-core-5.4.1.jar:na]
    at $HttpServletRequestHandler_94ac265764c4.service(Unknown Source) [na:na]
    at $HttpServletRequestHandler_94ac26576458.service(Unknown Source) [na:na]
    at info.code8.tapestry.TapestryFilter.doFilter(TapestryFilter.java:49) [tapestry-boot-0.1.0-SNAPSHOT.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
    at org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:151) [spring-orm-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

Lib 版本:

   tapestry           : 5.4.1
   hibernate          : hibernate-core-5.1.0.Final
   spring framework   : 4.2.5.RELEASE
   spring-boot        : 1.3.3.RELEASE
   spring-data-jpa    : 1.10.1.RELEASE   // for  querydsl 4 support
   spring-data-commons: 1.12.1.RELEASE   // for  querydsl 4 support

【问题讨论】:

不要使用 OpenSessionInViewFilter 你正在使用 JPA 使用 OpenEntityManagerInViewFilter 代替。 OpenSessionInView 用于普通休眠而不是 JPA。 @M.Deinum 成功了。谢谢!如果您将评论粘贴为答案,我会接受。 @M.Deinum 平!如果您将其添加为答案,我可以接受。 【参考方案1】:

OpenSessionInViewFilter 用于普通的 Hibernate API。而OpenEntityManagerInViewFilter 与 JPA api 一起使用(也适用于其他 JPA 提供程序)。

要解决您的问题,请使用适合您使用的技术的过滤器,在您的情况下为 OpenEntityManagerInViewFilter

【讨论】:

以上是关于使用 Spring Boot 和 Data JPA,尽管有 OpenSessionInViewFilter,但仍会出现 LazyInitializationException的主要内容,如果未能解决你的问题,请参考以下文章

使用 spring-data-jpa 和 MockMvc 进行 spring boot junit 测试

无法将 Spring Data MongoDB + Spring Data JPA 与 Spring Boot 一起使用

没有 Spring Boot 的 Spring Data JPA

Spring Boot + Spring Data JPA + 事务无法正常工作

Spring Boot:整合Spring Data JPA

使用spring boot和spring data jpa时一对多关系的奇怪行为