做的一个小项目里面需要根据不同的角色显示不同的菜单,于是将数据库设计为如下形式:

       用户表Admin(id, user_name, role_id)

       角色表Role(id, name)

       菜单表Menu(id, name, url)

       角色菜单表RoleMenu(id, role_id, menu_id)

   其中用户表和角色表存在一对一关联,角色表和菜单表存在着多对多关联。系统采用了Hibernate框架,各实体定义如下:

   

   

public class Admin implements Serializable{
    public Integer id;
    public Role role;
    …
    @OneToOne
    @JoinColumn(name=”role_id”)
        public Role getRole(){
        return this.getRole();
    }
}
public class Role implements Serializable{
    public Integer id;
    public Set<Menu> menus;
    …
    @ManyToMany
    @JoinTable(name=”role_menu” joinColumns=     {@JoinColumn(name="role_id")},
                inverseJoinColumns={@JoinColumn(name="menu_id")})
    public Set<Menu> getMenus(){
        return menus;
    }
}


用户登录采用ajax实现,登录成功后跳转到IndexAction动态地读取菜单信息,代码如下:

public Map<String, List<Menu>> findUserMenus(Admin admin) {
// TODO Auto-generated method stub
      Set<Menu>menus = admin.getRole().getMenus();
      Map<String,List<Menu>> map = new HashMap<String, List<Menu>>();
        for(Menu menu : menus){
            Stringid = menu.getId();
            if(id.length() > 2){
            StringparentId = id.substring(0, 2);
            MenuparentMenu = menuDao.queryById(parentId);
            Stringtext = parentMenu.getText();
            List<Menu>lstMenu = (List<Menu>)map.get(text);
            if(lstMenu == null){
                lstMenu= newArrayList<Menu>();
            }
            lstMenu.add(menu);
            map.put(text,lstMenu);
         }
      }
    return map;
}

   但登录成功后出现如下错误:

   org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:cn.edu.qfnu.main.model.Role.menus, could not initialize proxy - no Session

   若将Role实体中menusfetch类型改为EAGER则没有错。在web.xml中已经配置了OpenSessionInViewFilter折腾了很久才解决。原来OpenSessionInViewFilter用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定,也就是说,在一次请求过程中,Hibernate Session是不会关闭的,懒加载也因此能用。

   我的问题是,在登录请求后又发送了一次请求,此时通过session中保存的admin对象获取menus对象的Session已经关闭,因此会出现上述错误。

   记录下来,避免以后再犯类似的错误。