📜  org.hibernate.LazyInitializationException:无法初始化代理 [ua.tqs.ReCollect.model.User#2407] - 无会话 (1)

📅  最后修改于: 2023-12-03 15:33:20.591000             🧑  作者: Mango

org.hibernate.LazyInitializationException: 无法初始化代理 [ua.tqs.ReCollect.model.User#2407] - 无会话

这个异常通常发生在使用Hibernate进行对象关系映射(ORM)时。当我们在一个session中从数据库中获取到一个实体对象,并将其持久化到缓存中时,Hibernate会为该实体对象生成一个代理对象,并且只有在需要访问该实体属性时,才会从缓存中加载该实体对象。

但是当我们在session关闭之后,再次去访问该实体对象属性时,就会抛出上述的异常。这是因为此时代理对象已经找不到之前的session,无法从缓存中加载实体对象导致的。

通常解决这个问题的方法是在session未关闭时,通过方法Hibernate.initialize()来强制初始化代理对象。也可以通过配置文件hibernate.cfg.xml中添加<property name="hibernate.enable_lazy_load_no_trans">true</property>来允许无session的Lazy Initialization。

示例代码:

Session session = sessionFactory.openSession();
Transaction tx = null;
try {
    tx = session.beginTransaction();
    User user = (User) session.get(User.class, 2407);
    Hibernate.initialize(user); // 强制初始化代理对象
    tx.commit();
} catch (Exception e) {
    if (tx != null) {
        tx.rollback();
    }
    e.printStackTrace();
} finally {
    session.close();
}

对于web应用程序,通常需要在web的filter中打开session并进行初始化,以确保在控制器中可以正常访问持久化对象,例如:

public class HibernateSessionRequestFilter implements Filter {
 
    private SessionFactory sessionFactory;
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        sessionFactory = HibernateUtil.getSessionAnnotationFactory();
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        Session session = null;
        try {
            session = sessionFactory.openSession();
            Hibernate.initialize(yourEntity); // 强制初始化代理对象
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }
 
    @Override
    public void destroy() {
 
    }
}

以上是解决org.hibernate.LazyInitializationException的方法。