为了账号安全,请及时绑定邮箱和手机立即绑定

如何修复Java中的LazyInitializationException?

如何修复Java中的LazyInitializationException?

猛跑小猪 2022-09-07 16:05:06
我从事一个小项目,我有2个表,用户和应用程序。一个用户可以有多个应用程序,一个应用程序可能由多个用户使用,因此它们是它们之间的多对多关系。每个表都有一些字段(id,名称,密码,技术等),我还在User和Apprause类中声明了2个数组列表,并带有@ManyToMany的注释。问题是,在我的业务层中,我写了一个方法,应该向用户添加一个应用程序,当我尝试做user.getListOfApplications().add(app)时,它会给我这个例外...公共类管理器Hibernate { private SessionFactory sessionFactory;public void setup(){     sessionFactory = new Configuration().configure().buildSessionFactory();}public void exit(){    sessionFactory.close();}public void create(Object obj){    Session session = sessionFactory.openSession();    session.beginTransaction();    session.save(obj);    session.getTransaction().commit();    session.close();}public Object read(Class<?> c, int idObj){    Session session = sessionFactory.openSession();    session.beginTransaction();    Object obj = session.get(c, idObj);    System.out.println(obj);    session.getTransaction().commit();    session.close();    return obj;}public void update(Object obj){    Session session = sessionFactory.openSession();    session.beginTransaction();    session.update(obj);    session.getTransaction().commit();    session.close();}public void delete(Object obj){    Session session = sessionFactory.openSession();    session.beginTransaction();    session.delete(obj);    session.getTransaction().commit();    session.close();}public <T> List<T> loadAllData(Class<T> type){    Session session = sessionFactory.openSession();    session.beginTransaction();    CriteriaBuilder builder = session.getCriteriaBuilder();    CriteriaQuery<T> criteria = builder.createQuery(type);    criteria.from(type);    List<T> data = session.createQuery(criteria).getResultList();    session.getTransaction().commit();    session.close();    return data;}}
查看完整描述

2 回答

?
慕仙森

TA贡献1827条经验 获得超8个赞

当您使用以下方法管理器加载数据时,问题开始。


public <T> List<T> loadAllData(Class<T> type)

{

        // New session was opened here

        Session session = sessionFactory.openSession();

        session.beginTransaction();


        CriteriaBuilder builder = session.getCriteriaBuilder();

        CriteriaQuery<T> criteria = builder.createQuery(type);

        criteria.from(type);

        List<T> data = session.createQuery(criteria).getResultList();


        session.getTransaction().commit();

        session.close();

        //session is close here

        return data;

    }

因此,当您加载数据时,休眠框架将仅加载用户对象。由于您已选择在模型类中使用延迟加载,因此只有在您尝试访问列表时才会加载应用程序值。由于您已经关闭了会话,因此框架无法再获取应用程序列表,从而导致延迟加载异常。


listOfApplications = managerHibernate.loadAllData(Application.class);

//loading user data and close the session associated with it

listOfUsers = managerHibernate.loadAllData(User.class);

User user = null;

Application app = null;


for(Application index: listOfApplications)

{

  if(index.getApplicationName().equals(applicationName))

      {

          okApp = 1;

          app = index;

      }

}


for(User index: listOfUsers)

{

  if(index.getUserUserName().equals(userUserName))

      {

          okUser = 1;

          user = index;

      }

}


if(okUser == 0  || okApp == 0)

  return false;

else

{   

  // when you run this line the hibernate framework will try to retrieve the application data.Since you have the closed session lazy load exception occurs 

  user.getListOfApplications().add(app);

  return true;

}

解决此问题的方法


1)尝试保持会话打开状态,以便您的框架可以获取应用程序数据


2)在模型pojo类中将延迟加载更改为预先加载(因为您正在使用多对多关系,因此不建议以这种方式使用)


查看完整回答
反对 回复 2022-09-07
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

由于没有用于获取用户中应用程序的惰性列表的事务,因此您需要先获取它。为了做到这一点,你可以改变loadAllData,如下所示:


public interface CriteriaSpec 

{

public void joinFetch(CriteriaBuilder builder, CriteriaQuery criteria, Root root);

}


public <T> List<T> loadAllData(Class<T> type, Optional<CriteriaSpec> spec)

{

Session session = sessionFactory.openSession();

session.beginTransaction();


CriteriaBuilder builder = session.getCriteriaBuilder();

CriteriaQuery<T> criteria = builder.createQuery(type);

Root root = criteria.from(type);

if(spec.isPresent())

    spec.joinFetch(builder, criteria, root);

List<T> data = session.createQuery(criteria).getResultList();


session.getTransaction().commit();

session.close();

return data;

}

然后使用它:


managerHibernate.loadAllData(Application.class, Optional.empty());

listOfUsers = managerHibernate.loadAllData(User.class, (rootEntity, query, 

criteriaBuilder) -> {

            rootEntity.fetch("listOfApplications", JoinType.Left_OUTER_JOIN);


        });


查看完整回答
反对 回复 2022-09-07
  • 2 回答
  • 0 关注
  • 77 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信