首页 新闻 会员 周边

SPRINGMVC,SPRING4,HIBERNATE4.2.4使用懒加载在ACTION层提示没有session

0
悬赏园豆:30 [待解决问题]

我搭建的是一个SPRINGMVC+SPRING4+HIBERNATE4.2.4。但是我到在action层拿不到想要的数据。事物边界配置在了service层,提示说session关闭了。。但我又不想变成eager。应该怎么解决?

搭建的文件如下

web.xml中配置了配置文件openSessionInViewFilter

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    
    <filter>
        <filter-name>openSessionInViewFilter</filter-name>
        <filter-class>
              org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    
    <!-- 配置spring核心servlet 跳转的时候要用到-->  
    <servlet>  
        <servlet-name>spring</servlet-name>  
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
        <load-on-startup>1</load-on-startup>  
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-servlet.xml</param-value>
        </init-param>
    </servlet>  

    <servlet-mapping>  
        <servlet-name>spring</servlet-name>  
        <url-pattern>/</url-pattern>  
    </servlet-mapping>  
    
    <jsp-config>
        <taglib>
            <taglib-uri>/WEB-INF/tlds/arch5.tld</taglib-uri>
            <taglib-location>/WEB-INF/tlds/arch5.tld</taglib-location>
        </taglib>
    </jsp-config>    
</web-app>

CodeGroup实体与CodeType输入1对多关系而且使用了懒加载具体代码如下

@OneToMany(cascade =CascadeType.REFRESH,fetch=FetchType.LAZY)
@JoinColumn(name = "codeGroupId",referencedColumnName="id",insertable=false,updatable=false)
public List<CodeType> getCodeTypeList() {
return codeTypeList;
}

SimpleTag如下

package com.mvc.tag;


import java.io.IOException;
import java.util.List;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mvc.model.CodeGroup;
import com.mvc.model.CodeType;
import com.mvc.service.CodeGroupService;
import com.mvc.service.impl.CodeGroupServiceImpl;
public class SimpleTagTest extends SimpleTagSupport{
    

    private String groupvalue;
    public String getGroupvalue() {
        return groupvalue;
    }
    public void setGroupvalue(String groupvalue) {
        this.groupvalue = groupvalue;
    }

    @Override
    public void doTag() throws JspException, IOException {
        JspContext ctx = getJspContext();
        JspWriter out = ctx.getOut();
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        CodeGroupService codeGroupService = (CodeGroupService) ac.getBean("CodeGroupService");
        CodeGroup codeGroup = codeGroupService.getCodeGroupByGroupValue(groupvalue);
        List<CodeType> codeTypeList = codeGroup.getCodeTypeList();
        StringBuilder sb = new StringBuilder();
        sb.append("<select>");
        for(CodeType codeType:codeTypeList){
            sb.append("<option>"+codeType.getCodeName()+"</option>");
        }
        sb.append("</select>");
        out.println(sb.toString());
    }
}

 

异常信息报错信息如下

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mvc.model.CodeGroup.codeTypeList, could not initialize proxy - no Session
    at com.mvc.tag.SimpleTagTest.doTag(SimpleTagTest.java:40

不把lazy改成Eager如何解决

cailineng的主页 cailineng | 初学一级 | 园豆:172
提问于:2015-08-04 23:06
< >
分享
所有回答(5)
0

给一个方向,使用DTO来完成。新建一个Class类,把这两个类的信息拷贝到一个类中,(用beanUtils把这两个关联关系的类的信息拷贝到这个Class中)然后将这个Class类作为传输对象,这样就可以不开启懒加载。

叔本不华 | 园豆:202 (菜鸟二级) | 2015-09-07 19:33
0

提示session关闭一般是因为Spring认为你的一次请求已经完成所以session被关闭 即使有OpenSessionInViewFilter也是不起作用的 这个只有在一次请求中才起作用

qiuxs | 园豆:165 (初学一级) | 2015-10-07 14:26
0

在service里面添加Hibernate.initialize(codeGroup.getCodeTypeList());把lazy的加载上就可以了吧

之奇一昂 | 园豆:1421 (小虾三级) | 2015-10-13 10:35
0

这是一个精典的问题:
因为我们在hibernate里面load一个对象出来时,用到的是代理对象,也就是说当我们在执行load方法时并没有发sql语句,而是返回一个proxy对象。只有当们具体用到哪个get**方法时才会发sql语句,才会去数据库查。但是当我们把打开session,关闭session交给了srping去做时,当们load完之后我们的session就会被srping关闭,如果我们在jsp页面或者其它的地方再去用get方法取值时就会报这个错误。
解决方法一:但如果我们在hibernate用get方法就可以解决取单个对象的问题,因为get方法直接发sql语句,把我们想的数据从数据库中get出来然后放在内存中。
如果我们取单个对象可以用get方法没有问题;但是如果我们取的的对象还有关联对象时用get就有问题,因为它不会把关联的对象取出来,但如果页面上用到关联的对象时也会报no session的问题
解决方法二:用到srping的filter(要加在strutsfilter有前面,因为它也有先后顺序,有先进先出的原则)
在我们的web.xml里面加上

<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这样做就是让opensession closesession全交给视图部分,最后视图部分用完了session再去关session就不会有上面的错误了

 

npe0 | 园豆:1299 (小虾三级) | 2016-02-25 09:14
0

hibernate4.3.5.Final你好  ,你能给我发一个这个资源吗?yang_shuang163@163.com  

YOYOYS | 园豆:210 (菜鸟二级) | 2017-10-14 01:30
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册