Struts Spring Hibernate中的惰性初始化Hibernate

时间:2012-04-10 08:02:38

标签: spring hibernate struts

我将当前用户保存在会话中,当我使用当前用户(例如:user.getRole.getRoleName())时,我得到了LIE。我怎么能解决这个问题,我的代码是这样的

控制器:

public String home(){
    Users users = userService.getCurrentUser();
    if(users.getRole().getRoleName().equals("admin")){ //causing LIE
    ....
}

UserService:

@Override
public Users getCurrentUser(){
    session =  ActionContext.getContext().getSession();
    return (Users) session.get("user");
}

但是,当我将userService.getCurrentUser()更改为这样时,错误已解决,但我认为这不是正确的方式,因为每次使用当前用户时都需要连接到数据库。

@Override
public Users getCurrentUser(){
    session =  ActionContext.getContext().getSession();
    return daoManager.getDetailUser(((Users) session.get("user")).getUsername());
}

DaoManager.getDetailUser就像这样

@Override
public Users getDetailUser(String username) {
    try {
        Users user = (Users)sessionFactory.getCurrentSession().createQuery("SELECT U FROM Users U WHERE U.username=:USERNAME")
             .setParameter("USERNAME", username)
             .uniqueResult();
        return user;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

还有其他更好的方法来解决这个问题吗?谢谢。

2 个答案:

答案 0 :(得分:1)

最可能的解释是Spring在退出服务层(UserService)时关闭当前会话,但是,在此之后,因为Hibernate试图延迟加载子对象以避免不必要地加载数据(另见What is lazy loading in Hibernate?)。

要避免这种情况,您可以通过在fetch=FetchType.EAGER上指定role来确保hibernate不进行延迟加载,或者使用OpenSessionInView模式(但是,有时会将其视为反模式) ,见Why is Hibernate Open Session in View considered a bad practice?)。

答案 1 :(得分:1)

解决此问题的最简单方法是在会话关闭之前访问延迟获取的字段:

@Override
public Users getCurrentUser(){
    session =  ActionContext.getContext().getSession();
    Users user = (Users) session.get("user");
    user.getRole(); //Accessed to resolve lazy field
    return user;
}

我不推荐使用FetchType.EAGER。有了它你无法控制访问,无论你是否需要它都会被提取。为你的数据模型添加一些EAGER字段,然后突然你为最简单的请求提取整个数据库..

对于查询,您还可以使用JOIN FETCH