我搭建的是一个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如何解决
给一个方向,使用DTO来完成。新建一个Class类,把这两个类的信息拷贝到一个类中,(用beanUtils把这两个关联关系的类的信息拷贝到这个Class中)然后将这个Class类作为传输对象,这样就可以不开启懒加载。
提示session关闭一般是因为Spring认为你的一次请求已经完成所以session被关闭 即使有OpenSessionInViewFilter也是不起作用的 这个只有在一次请求中才起作用
在service里面添加Hibernate.initialize(codeGroup.getCodeTypeList());把lazy的加载上就可以了吧
这是一个精典的问题:
因为我们在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里面加上
hibernate4.3.5.Final你好 ,你能给我发一个这个资源吗?yang_shuang163@163.com