问题描述:
在做BOS物流管理系统的时候,点击区域页面显示配送区域信息,这个时候后台显示了no session的错误
org.apache.struts2.json.JSONException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.itheima.domain.Area.subareas, could not initialize proxy - no Session
at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:246)
at org.apache.struts2.json.JSONWriter.processCustom(JSONWriter.java:178)
at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:168)
at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:134)
at org.apache.struts2.json.JSONWriter.array(JSONWriter.java:492)
at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:158)
at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:134)
at org.apache.struts2.json.JSONWriter.map(JSONWriter.java:447)
at org.apache.struts2.json.JSONWriter.process(JSONWriter.java:154)
at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:134)
at org.apache.struts2.json.JSONWriter.write(JSONWriter.java:102)
at org.apache.struts2.json.JSONUtil.serialize(JSONUtil.java:107)
at org.apache.struts2.json.JSONResult.createJSONString(JSONResult.java:203)
at org.apache.struts2.json.JSONResult.execute(JSONResult.java:177)
at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:369)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:273)
at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:139)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244)
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
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:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.itheima.domain.Area.subareas, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:563)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:205)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:542)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:133)
at org.hibernate.collection.internal.PersistentSet.equals(PersistentSet.java:423)
at java.util.Vector.indexOf(Vector.java:411)
at java.util.Vector.contains(Vector.java:370)
at org.apache.struts2.json.JSONWriter.value(JSONWriter.java:117)
at org.apache.struts2.json.JSONWriter.add(JSONWriter.java:401)
at org.apache.struts2.json.JSONWriter.bean(JSONWriter.java:231)
... 81 more
看系统提示可以看出来是因为加载Area类中的subareas属性出现了问题。我们再来看下Area类中有哪些属性
@Id
@Column(name = "C_ID")
private String id;
@Column(name = "C_PROVINCE")
private String province; // 省
@Column(name = "C_CITY")
private String city; // 城市
@Column(name = "C_DISTRICT")
private String district; // 区域
@Column(name = "C_POSTCODE")
private String postcode; // 邮编
@Column(name = "C_CITYCODE")
private String citycode; // 城市编码
@Column(name = "C_SHORTCODE")
private String shortcode; // 简码
@OneToMany(mappedBy = "area")
private Set<SubArea> subareas = new HashSet<SubArea>();
为什么Area中这么多属性,只有subareas属性出现了问题?可以看出来这里的subareas是一个集合,问题就出现在这里,在spring框架中集合属性的查询默认的是懒加载的,也就是说在service层调用dao层的查询方法时,dao层并不会向数据库发送查询语句,而是将查询语句藏在了session的一级缓存区域,在下一次subareas被使用到的时候才会真正向数据区发送查询语句,这样的好处是可以为系统节省资源,但是同样也带来一个问题,因为我们第一次调用subareas是在web层将查询到的数据打包成json数据的时候,但是我们的session在service层就已经被关闭了,我们都知道sss框架和ssh框架的底层都是Hibernate中的session对象对数据库进行操作的。因此就会出现no session的异常。
问题解决:
第一种:让session存活到web层
添加OpenEntityManagerInViewFilter过滤器(必须配置在struts拦截器前),原理就是将session的创建和关闭放在过滤器中,这样就可以让session存活到web层。
第二种:立即加载(不建议)
立即加载就是消除懒加载,运用JPA注解的属性fetch=FetchType.EAGER
@OneToMany(mappedBy = "area",fetch=FetchType.EAGER)
private Set<SubArea> subareas = new HashSet<SubArea>();
这样就可以在dao层立即加载subareas,这样在web层就可以直接使用到subareas的数据了。
第三种:取消序列化
如果subareas这个属性并不是需要的数据的话,可以通过注解让json在序列化Area的属性的时候,跳过subareas这个属性。这样就不需要向数据库查询subareas的数据了,也就不会出现懒加载的问题了。