在配置struts2+hibernate+spring的时候,我这里出现了这么一个问题,使用hibernate配置多对多的映射关系的时候,使用懒加载模式的话会出现这么一个错误:
Caused by:org.hibernate.LazyInitializationException: failed to lazily initialize acollection of role: domain.Department.menberList, could not initialize proxy -no Session
我的是用户与部门之间的多对多的映射关系,相关代码如下:
@ManyToMany(mappedBy = "menberList", cascade = CascadeType.MERGE)
public Set<Department> getDepartments() {
return departments;
}
@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(
name = "department_person",
joinColumns = @JoinColumn(name = "department_id"),
inverseJoinColumns = @JoinColumn(name = "person_id")
)
public Set<Person> getMenberList() {
return menberList;
}
如代码所示,我没有将懒加载模式设置为false,因为我觉得这样做的话会严重影响系统的性能,当然赶项目的同学可以将懒加载模式设置为false,方法就是在@ManyToMany注解中添加一个fetch = FetchType.EAGER,注意是两边都要加。这样就不会有什么问题,但是会严重影响系统性能。比如我们查询部门的信息,但是系统连带部门里面的员工全部的信息都查出来了,这大多数时候是不需要的。
好吧,回到最开始的问题,出现了这么一个exception,这么解决呢?
在度娘上面找了好久,发现基本都是同一个回答:
在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>
好吧,小编一样照抄了进去,发现有出现了一个新的问题,
No WebApplicationContext found: noContextLoaderListener registered?
好吧,相信大家已经麻木了,在问题解决之前又出现更多的问题。
小编又到度娘上面找,大多数都说解决办法是声明ContextLoaderListener 这个监听器,在web.xml里面配置如下:
<listener>
<listener-class>com.j.chat.upgrade.web.core.SystemLaunchListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config.xml</param-value>
</context-param>
小编配置了之后又出现了一个问题……反正就是打不开了。。。
最后小编自己想了好几天,发现这么做就可以。小编是个编程菜鸟,在获取Session的时候一律采用getCurrentSession()的方式,现在才发现是不行的,当我们需要用到懒加载的时候使用openSession()获取Session就可以正常运行。当我们添加、删除、修改的时候可以使用getCurrentSession,但是当我们查询的时候如果有多对多的映射关系的话就应该使用openSession(),这样的话我们在使用懒加载的时候才不会出现Session has close的情况。
刚才我们使用openSession新建了一个回话,但是我们并不能关闭它,马上关闭的话懒加载就不能实现了。好吧,那我们不关闭它,可是后来我执行了一条update语句。出现了下面这个错误
Illegal attempt to associate a collection with two open sessions
这个错误的意思大概是有两个session引用了同一个collection对象,后来我的解决办法是修改dao层的update代码:
如下:
public void update(T entity) {
Session session = getSessionFactory().openSession();
Transaction transaction =session.beginTransaction();
session.update(session.merge(entity));
transaction.commit();
}
有兴趣的同学可以百度一下session.merge,由于我也是个菜鸟,这里就不做解释了。
在web.xml里面加上了如下代码:<filter>
<filter-name>opensession</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>opensession</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
注意这个代码放在struts2过滤器的后面,网上的说法是跟循序有关,我这里就不做测试了。