今天点背,在用ssh2做oa项目时碰到一个诡异的bug!(这个struts2里面的异常竟然不抛出来!)
项目背景为:User类有属性Set<Role> roles, Role类有属性:Set<Privilege> privileges,
然后用户登陆后,在web的session中存放了user这个对象,并且在jsp页面中通过
<s:if test="#session.user.hasPrivilegeByName(privilegeName)">调用user的hasPrivilegeByName(privilegeName)方法
public class User{
......
public boolean isAdmin(){
return name.equals("admin");
}
//检测本用户是否拥有该权限
public boolean hasPrivilegeByName(String privilegeName){
//超级管理员拥有所有权限
if(isAdmin()){
return true;
}
for (Role role : roles) {//debug发现每次执行到这行代码就直接跳出了,这个hasPrivilegeByName方法就执行完毕了!!
for (Privilege privilege : role.getPrivileges()) {
if (privilegeName.equals(privilege.getName())) {
return true;
}
}
}
return false;
}
......
}
一脸懵逼!!什么情况,每次debug到for (Role role : roles)这一行,这个 hasPrivilegeByName方法就直接执行完毕了,没有任何异常信息!!
最后无意间我发现在Role.hbm.xml文件里
<set name="privileges" table="role_privilege" cascade="all" >
<key>
<column name="role_id"></column>
</key>
<many-to-many class="Privilege" column="privilege_id"></many-to-many>
</set>
没有配上lazy="false"
于是马上加上这个属性
然后功能就正常执行了!!!
----------------------------------------------------------------------------------------------------------------------
所以为什么代码执行到这一句直接跳出这个方法------------>是因为这里发生了懒加载异常!!
而且最恶心的是这个这个异常竟然没有在tomcat后台抛出来!!这真的是struts2的设计的一个小bug,给我们开发调试造成了很大的困扰!!
----------------------------------------------------------------------------------------------------------------------
至于为什么这里会发生懒加载异常,这里要说明一下!
尽管我在web.xml中配置了OpenSessionInViewFilter,但是
1)当我第一次请求,便从数据库中通过hibernate的session取出对应user对象,并且通过ActionContext.getContext().getSession().put("user",user)把 这个user对象保存到web层的session中,当这次的请求结束后,hibernate的事务结束,session也就在OpenSessionInViewFilter中关闭了,所以这个user对象便从持久化状态转为游离状态。
2)当再次请求时,因为会话没结束,程序仍可从web的session中取出那个游离的user对象,此时调用user.getRoles()、 role.getPrivileges() 自然而然会发生懒加载异常!!所以必须要配置lazy=“false”属性