【问题标题】:Using openEntityManagerInView still getting "failed to lazily initialize a collection of role"使用 openEntityManagerInView 仍然“无法懒惰地初始化角色集合”
【发布时间】:2025-11-26 07:40:01
【问题描述】:

我正在尝试将我的一个实体返回到 JSP 页面,但收到以下错误“无法延迟初始化角色集合”。我添加了 openEntityManagerInView 过滤器(假设它允许实体管理器在视图中保持打开状态?)但仍然出现此错误。

我的应用程序是使用 java config no xml 配置的。

下面是我的调度程序 serverlet。你可以看到我已经添加了 openEntityManagerInView 过滤器。

有什么想法吗?我在 * 上检查了类似的问题,但对所提供的解决方案没有运气。

public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {

    registerOpenEntityManagerInViewFilter(servletContext);
    super.onStartup(servletContext);

}

private void registerOpenEntityManagerInViewFilter(ServletContext servletContext) {
    OpenEntityManagerInViewFilter viewFilter = new OpenEntityManagerInViewFilter();
    viewFilter.setEntityManagerFactoryBeanName("entityManagerFactory");
    FilterRegistration.Dynamic registration = servletContext.addFilter("openEntityManagerInView",
            new OpenEntityManagerInViewFilter());
    registration.addMappingForUrlPatterns(null, false, "/*");

}

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[]{Config.class, SecurityConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[]{WebConfig.class};
}

@Override
protected String[] getServletMappings() {
    return new String[]{"/"};
}

}

下面是有问题的实体。我省略了 getter 和 setter。

@Entity
@Table(name = "film")
public class Film {

@Id
@GeneratedValue
@Column(name = "film_id")
private int filmId;
@Column(name = "title")
private String title;
@Column(name = "description")
private String description;
@Column(name = "release_year")
private int releaseYear;
@ManyToOne
@JoinColumn(name = "language_id")
private Language language;
@ManyToOne
@JoinColumn(name = "original_language_id")
private Language originalLanguage;
@Column(name = "rental_duration")
private int rentalDuration;
@Column(name = "rental_rate")
private double rentalRate;
@Column(name = "length")
private int length;
@Column(name = " replacement_cost")
private double replacementCost;
@Column(name = "rating")
private String rating;
@Column(name = "special_features")
private String specialFeatures;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "last_update")
private Date lastUpdate;
@OneToMany(mappedBy = "film", cascade = CascadeType.ALL)
private List<Inventory> inventories;

.........
}

下面是我的 JPA 配置。

@Configuration
@EnableTransactionManagement
public class Config {

@Bean(name = "entityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
    HibernateJpaDialect hibernateJpaDialect = new HibernateJpaDialect();
    emf.setDataSource(dataSource());
    emf.setPackagesToScan("com");
    emf.setJpaDialect(hibernateJpaDialect);
    emf.setJpaVendorAdapter(hibernateJpaVendorAdapter);
    /* Map<String,String> props = new HashMap<>();
     props.put("hibernate.show_sql", "true");
     emf.setJpaPropertyMap(props);*/
    emf.afterPropertiesSet();
    return emf.getObject();
}

@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager() throws IOException {
    JpaTransactionManager jtm
            = new JpaTransactionManager();
    jtm.setEntityManagerFactory(entityManagerFactory());
    jtm.setDataSource(dataSource());
    return jtm;
}

@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
    DriverManagerDataSource dds = new DriverManagerDataSource();
    dds.setDriverClassName("com.mysql.jdbc.Driver");
    dds.setUrl("jdbc:mysql://localhost/test");
    dds.setUsername("username");
    dds.setPassword("password");
    return dds;
}

}

以下是我的网络配置

@Configuration
@EnableWebMvc
@ComponentScan("com")
public class WebConfig {

@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setViewClass(JstlView.class);
    vr.setPrefix("/WEB-INF/jsp/");
    vr.setSuffix(".jsp");
    vr.setExposeContextBeansAsAttributes(true);
    return vr;
}

}

以下是我的安全配置。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void configureAuthenticationManagerBuilder(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
     .antMatchers("/**").access("hasRole('ROLE_USER')")
     .and().formLogin().loginPage("/login")
     .usernameParameter("username")
     .passwordParameter("password")
     .defaultSuccessUrl("/index", true).failureUrl("/login?error")
     .loginProcessingUrl("/j_spring_security_check");

}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/login");
}

}

下面是我的道课。

@Repository
public class FilmDao {

    @PersistenceContext
    private EntityManager em;

    public Film getFilm(int filmId) {
        Film film = em.find(Film.class, filmId);
        return film;
    }

}

下面的服务类由我的控制器调用。

@Service
public class FilmService {

    @Autowired
    private FilmDao filmDao;

   @Transactional
    public Film getFilm(int filmId) {
        Film film = filmDao.getFilm(filmId);
        return film;
    }

}

下面的堆栈跟踪。

14:48:30,416 ERROR [io.undertow.request] (default task-6) UT005023: Exception handling request to /test-app/WEB-INF/jsp/update_inventory.jsp: org.apache.jasper.JasperException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.jm.sakila.entity.Film.inventories, could not initialize proxy - no Session
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:410) [jastow-1.0.0.Final.jar:1.0.0.Final]
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:326) [jastow-1.0.0.Final.jar:1.0.0.Final]
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:259) [jastow-1.0.0.Final.jar:1.0.0.Final]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:82) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:192) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:160) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1244) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1027) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178) [spring-orm-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.9.RELEASE.jar:3.2.9.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:197) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_45]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_45]
    at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_45]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.jm.sakila.entity.Film.inventories, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:576) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:215) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:555) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:143) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.toIterator(ForEachSupport.java:72) [jboss-jstl-api_1.2_spec-1.1.2.Final.jar:1.1.2.Final]
    at org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:66) [jboss-jstl-api_1.2_spec-1.1.2.Final.jar:1.1.2.Final]
    at javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:241) [jboss-jstl-api_1.2_spec-1.1.2.Final.jar:1.1.2.Final]
    at org.apache.jsp.WEB_002dINF.jsp.update_005finventory_jsp._jspx_meth_c_005fforEach_005f1(update_005finventory_jsp.java:231)
    at org.apache.jsp.WEB_002dINF.jsp.update_005finventory_jsp._jspx_meth_c_005fif_005f1(update_005finventory_jsp.java:194)
    at org.apache.jsp.WEB_002dINF.jsp.update_005finventory_jsp._jspService(update_005finventory_jsp.java:83)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:69) [jastow-1.0.0.Final.jar:1.0.0.Final]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:366) [jastow-1.0.0.Final.jar:1.0.0.Final]
    ... 86 more

谢谢。

【问题讨论】:

  • 你能发布异常堆栈跟踪吗?
  • 是的,请发布异常日志。
  • @DavidR 添加了完整的 stracktrace 谢谢。
  • @premkumar 添加了完整的 stracktrace 谢谢
  • 配置了 OEMIV 过滤器应该允许您延迟加载视图,所以我只能猜测过滤器配置不正确。对 super.onStartup(servletContext) 的调用可能会覆盖新创建的过滤器。将此行移到对 registerOpenEntityManagerInViewFilter(servletContext); 的调用上方;

标签: java spring hibernate jpa


【解决方案1】:

我遇到了同样的问题。 SecurityFilter 具有默认过滤顺序 -100,这就是原因。您必须在 SecurityFilter (安全过滤器检查用户的角色并失败)之前放置 openEntityManagerInViewFilter (其顺序等于 0 或类似的东西)。尝试使用 order=-101 注册过滤器。您可以将您的方法与 ServletContext 或我使用的以下方法一起使用(只需插入任何标有 @Configuration 注释的 bean):

@Configuration
public class WebConfig {
@Bean
    public FilterRegistrationBean openEntityManagerInViewFilterRegistration(SecurityProperties properties) {

        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(openEntityManagerInViewFilter());
        registration.addUrlPatterns("/*");
        registration.setOrder(properties.getFilterOrder()-1);
        registration.setName("openEntityManagerInViewFilter");
        registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
        return registration;
    }

    @Bean(name = "openEntityManagerInViewFilter")
    public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
        return new OpenEntityManagerInViewFilter();
    }
}

主入口点(主类)

@Configuration
@SpringBootApplication
public class Application  extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    static final Logger log = LoggerFactory.getLogger(Application.class);
    public static void main(String[] args) {

        ConfigurableApplicationContext run = SpringApplication.run(Application.class);
        log.info(Arrays.toString(run.getEnvironment().getActiveProfiles()));
    }

}

【讨论】:

  • 试过这仍然不起作用,删除了我所有的弹簧安全材料,仍然是同样的问题。你在使用 org.springframework.boot jar 中的 FilterRegistrationBean 吗?下面是我使用的导入 org.springframework.boot.context.embedded.FilterRegistrationBean
  • 我使用了 org.springframework.boot.context.embedded.FilterRegistrationBean。
  • 我将更新我的答案,因为我无法在评论中发布它
  • 对 Spring Boot 不太熟悉,我假设我的应用程序必须是 Spring Boot 应用程序才能使 FilterRegistrationBean 工作?
  • 对此不确定。你在哪里将我的 WebConfig 添加到 getServletConfigClasses 或 getRootConfigClasses?
【解决方案2】:

问题很简单。

在您的 jsp 中,您将返回来自 public Film getFilm(int filmId) 的电影 在 jsp 页面中,您可能会执行以下操作:

<jsp:getProperty name="film" property="inventories" />

您正在尝试获取库存,但它是延迟加载并且会话已经关闭(@Transactional 注释打开会话并在方法完成时关闭)

因此,您要么创建新方法以通过filmId 获取inverntories,要么使其快速加载:

@OneToMany(fetch=FetchType.EAGER, mappedBy = "film", cascade = CascadeType.ALL)
private List<Inventory> inventories;

【讨论】:

  • 我已经知道这一点,为了克服延迟加载问题,我使用了 openEntityManagerInView 过滤器,因此实体管理器在我的视图中保持打开状态也允许访问列表。但似乎过滤器没有做任何事情,不知道为什么?
  • 对不起,我不熟悉过滤器功能。我知道他应该在视图(jsp)中保持会话打开。如果你一直在使用这个领域,为什么不让它变得急切呢?我猜过滤器是错误的。过滤器的代码是什么?
  • 你确定bean "entityManagerFactory" 被调用了吗?
【解决方案3】:

事务在 JSP 渲染之前完成,因此 Hibernate Session 不再可用于延迟加载所述属性。

替代解决方案(不需要使用 OEMIV 过滤器):如果您希望在代码中的其他位置保留所述集合属性的延迟加载,请创建一个单独的查找器方法 findFilmWithInventories 用于检索实体并执行join fetch 查询以急切地加载所述集合。

【讨论】:

  • 鉴于用户正在尝试在视图模式中使用开放实体管理器,这在另一个不正确的答案中。
  • 如果您仔细阅读,OP 会尝试通过使用上述过滤器来解决问题。发布替代解决方案并不构成“错误答案”。
  • 如果他尝试使用 OEMIV,我猜他知道在呈现 JSP 时会话默认不再可用。正确的答案是告诉他过滤器为什么不起作用。
  • 根本问题是延迟加载不起作用。如果 OP 希望继续解决 OEMIV 的问题,我可以接受。但如果他选择探索其他解决问题的方法,那么我的回答可能会对他有所帮助。圣诞快乐。
  • OP 的问题是延迟加载事务之外的实体,OSIV 只是一种变通方法,而不是问题本身。因此,IMO,这个答案是完全可以接受的,不赞成投票是不合适的。 +1 补偿:)
【解决方案4】:

或许,在这种情况下,要简单得多,放弃OpenSessionInView/OpenEntityManagerInView,而使用

<property name="hibernate.enable_lazy_load_no_trans" value="true" />

在 persistence.xml 中(或以编程方式配置)。

此属性具有与 OSIV 类似的行为(以及优缺点),除了可以在每个延迟加载触发器上实例化一个新的 EntityManager,而不是具有一个单独的长范围的,因此您必须注意它以正确管理持久性上下文。

但是,这永远不会因 no Session 而失败。

【讨论】:

  • 我强烈建议不要使用 Hibernate 的该功能。自动创建一个新的 EntityManager 来加载未获取的惰性关联意味着这些请求之间没有一级缓存。您可以轻松地最终导航一个对象图,其中,通过两个不同的路径导航到同一个数据库对象,您最终可能会得到同一个对象的两个不同实例。假设您要更改该逻辑对象,并且要将其合并回数据库。 Hibernate 将拒绝合并它,因为它会为同一个逻辑实体找到两个单独的对象实例。
  • 我什至没有提到你根本没有事务隔离。
  • 对不起,我不同意。您不应该以绝对的方式反对某些功能。由于我们谈论的是 OSIV,因此 OP 可能已经用于管理 detached 实体(以及同一实体的不同实例)。至于事务隔离,我没有看到问题,因为 enable_lazy_load_no_trans 是关于延迟加载 而不 使用事务。
  • 造成问题的不是分离的对象。问题是这个解决方案实际上改变了在先前事务中加载的对象图的内存表示,而没有 JPA 解决方案的一级缓存提供的通常的引用完整性保证。而且也没有任何事务隔离保证。
【解决方案5】:

您可以简单地在您的@Transactional 服务层内的某处调用film.getInventories()。这为您提供了更多控制权,而不是在 JPA 级别上急切加载:

@Service
public class FilmService {

   @Autowired
   private FilmDao filmDao;

   @Transactional
    public Film getFilm(int filmId, boolean loadInventories) {
        Film film = filmDao.getFilm(filmId);
        if(loadInventories){ film.getInventories(); }
        return film;
    }
}

由于它需要另一个往返 DB,我建议添加一些缓存。

您还可以像这样添加通用字段加载功能:

   @Transactional
    public Film getFilm(int filmId, String[] propertiesToLoad) {
        Film film = filmDao.getFilm(filmId);
        BeanWrapper bw = new BeanWrapperImpl(item);
        for (String propertyName : propertiesToLoad) {
           bw.getPropertyValue(propertyName);
        }
        return film;
    }

【讨论】:

    最近更新 更多