2012-03-26 4 views
2

Я получаю ленивое исключение инициализации. A имеет метод контроллера с аннотацией @Transactional, он вызывает метод службы (он не имеет аннотации @Transactional), и, наконец, внутри этого метода я вызываю еще один весенний компонент (он проверяет, имеет ли пользователь правильную роль).Lazy Инициализация с @Transactional

В проекте я использовал @Transactional, и у меня нет проблем. Но в этом случае у меня есть ленивое исключение инициализации.

Я что-то упустил?

Вот код:

и вот метод, который первым выполняется. Он имеет аннотацию @Transactional

@Transactional 
    public CompanyForm edit(){ 
     CompanyForm form = new CompanyForm(); 
     Company company = companyService.findMainOne(getLoggedUser()); 
     if (company != null) { 
      if (company != null) 
       modelMapper.map(company, form); 
     } 
     return form; 
    } 

Это метод в службе, где код называется

@Autowired 
    private UserVisitorHasBussinessRole hasBussinessRole; 

@Override 
    public Company findMainOne(User user) { 
     if (user == null) 
      throw new NullPointerException("the user can not be null"); 
     user.accept(hasBussinessRole); 
     List<Company> companies = this.companyRepository.findOwnedBy(user 
       .getId()); 
     if (companies != null && companies.size() > 0) 
      return companies.get(0); 
     return null; 
    } 

Этот компонент проверяет, имеет ли пользователь надлежащую роль. Это где я получил исключение

@Component 
public class UserVisitorHasBussinessRole implements UserVisitor { 

    @Autowired 
    private Messages messages; 

    @Override 
    public void visit(SystemUser user) { 
     if(user == null || user.getUserRoles() == null || user.getUserRoles().isEmpty()) 
     { 
      String message = messages.get("hasBussinesRoleVisitor.noRole"); 
      throw new RuntimeException(message); 
     } 
     Boolean hasRole = false; 
     for (UserRole role : user.getUserRoles()) { 
      if(role instanceof UserRoleBusiness){ 
       hasRole = true; 
       break; 
      } 
     } 
     if(!hasRole) 
     { 
      String message = messages.get("hasBussinesRoleVisitor.noRole"); 
      throw new RuntimeException(message); 
     } 
    } 

    @Override 
    public void visit(SocialUser user) { 
     String message = messages.get("hasBussinesRoleVisitor.noRole"); 
     throw new RuntimeException(message); 
    } 

} 

Это где исключение

user.getUserRoles().isEmpty() 

Субъект:

@Entity 
@DiscriminatorValue(value = "BU") 
public class SystemUser extends User { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 3845147625976106863L; 

    // for joing the tables (many-to-many) 
    @ManyToMany(cascade = CascadeType.ALL, targetEntity = UserRole.class) 
    @JoinTable(name = "systemUser_userRole", joinColumns = { @JoinColumn(name = "system_user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_Id") }) 
    private List<UserRole> userRoles; 

    /** 
    * the list of user roles 
    * @return the user roles 
    */ 
    public List<UserRole> getUserRoles() { 
     return userRoles; 
    } 

    /*** 
    * set the list of user roles 
    * @param userRoles the user roles 
    */ 
    public void setUserRoles(List<UserRole> userRoles) { 
     this.userRoles = userRoles; 
    } 
} 

Я получаю следующее исключение

java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at ar.com.held.model.user.User.accept(Unknown Source) 
    at ar.com.held.service.implementation.CompanyServiceImpl.findMainOne(Unknown Source) 
    at ar.com.held.service.implementation.CompanyServiceImpl$$FastClassByCGLIB$$d0027e0c.invoke(<generated>) 
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) 
    at ar.com.held.service.implementation.CompanyServiceImpl$$EnhancerByCGLIB$$b15b3940_2.findMainOne(<generated>) 
    at ar.com.held.controller.CompanyFlowController.edit(CompanyFlowController.java:28) 
    at ar.com.held.controller.CompanyFlowController$$FastClassByCGLIB$$c3823c4.invoke(<generated>) 
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) 
    at ar.com.held.controller.CompanyFlowController$$EnhancerByCGLIB$$5b3921c7_2.edit(<generated>) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69) 
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:109) 
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57) 
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102) 
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:97) 
    at org.springframework.binding.expression.spel.SpringELExpression.getValue(SpringELExpression.java:84) 
    at org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:75) 
    at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188) 
    at org.springframework.webflow.execution.AnnotatedAction.execute(AnnotatedAction.java:145) 
    at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51) 
    at org.springframework.webflow.engine.ActionList.execute(ActionList.java:155) 
    at org.springframework.webflow.engine.Flow.start(Flow.java:534) 
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:366) 
    at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:225) 
    at org.springframework.webflow.executor.FlowExecutorImpl.launchExecution(FlowExecutorImpl.java:140) 
    at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:193) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129) 
    at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ar.com.held.model.user.SystemUser.userRoles, no session or session was closed 
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:393) 
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:385) 
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:125) 
    at org.hibernate.collection.internal.PersistentBag.isEmpty(PersistentBag.java:249) 
    at ar.com.held.service.implementation.visitor.UserVisitorHasBussinessRole.visit(Unknown Source) 
    ... 100 more 

ответ

2

Это происходит, когда ленивый инициализированный объект считывается, когда исходная транзакция уже завершена. Другими словами, когда вы возвращаете что-то из метода с аннотацией @Transactional, все объекты должны быть инициализированы (без обращения к ленивым объектам после возврата из метода). Поэтому в этом случае используйте lazy = "false", чтобы решить проблему (или принудийте ленивую инициализацию внутри метода).

+0

Спасибо! Но как я могу заставить ленивую инициализацию внутри метода? вызов user.getUserRoles(). size()? –

+1

Итерацию по всем связанным элементам и вызов любого получателя, за исключением уже загруженного getId(). Я бы предложил изменить отображение гибернации, чтобы сделать его ленивым = «false» –

+0

Ну, я решил. Я должен использовать @LazyCollection (LazyCollectionOption.FALSE) –

0

Добавить @Transactional в findMainOne и visit(SystemUser), чтобы они оба участвовали в одной и той же транзакции, тем самым предоставляя им доступ к сеансу/сущности-менеджера для компонентов, связанных с ленивой загрузкой. Или вы можете загрузить те компоненты, которые могут понадобиться, перед вызовом findMainOne.

+0

Когда я вернусь домой, я буду исследовать его. Но я думаю, что я это пробовал. –

3

Я решил с помощью @LazyCollection (LazyCollectionOption.FALSE)

вот код:

@ManyToMany(cascade = CascadeType.ALL, targetEntity = UserRole.class) 
@JoinTable(name = "systemUser_userRole", joinColumns = { @JoinColumn(name = "system_user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_Id") }) 
@LazyCollection(LazyCollectionOption.FALSE) 
private List<UserRole> userRoles; 

Это не лучшее решение, но это работает. Проблема в том, что аннотация LazyCollection представляет собой аннотацию Hibernate, а не jpa.

Всего

Смежные вопросы