如何在Hibernate中初始化一个Lazily加载的集合?

时间:2014-04-26 20:36:22

标签: java hibernate

当Hibernate加载所有内容时,我对如何构造代码感到困惑。

正如我现在所做的那样,当我尝试将一些数据加载到我的对象中时,我得到了Could not initialize proxy - no session异常。

目前的代码如下:

安排课程

public class MyScheduler {
  private static ItemRepo repo;
  private static List<Item> myItems;

  public MyScheduler() {
    if (myItems == null) {
      repo = new MyItemHibernateRepository();
      myItems = repo.findAll();
    }
  }
  // ... rest of code

查找所有方法v.1

  @Override
  public List<Item> findAll() {
    Session session = openSession();
    List<Item> transfers = 
        (List<Item>) session.createQuery("from Items").list();
    session.close();  
    return transfers;
  }

在这里,正如您所看到的,我尝试从数据库加载所有内容,将它们打包到列表中,然后将它们返回给调用者。但是,当我测试它时,问题是它们实际上并没有“加载”。我尝试稍后在程序中使用它们,我得到一个No Session错误。

在阅读了一下之后,似乎需要在session关闭之前初始化它们,因此,在我关闭会话之前,我添加了对Hibernate.initialize的调用

查找所有方法v.2

  @Override
  public List<Transfer> findAll() {
    Session session = openSession();
    List<Item> transfers = 
        (List<Item>) session.createQuery("from Items").list();

    transfers.forEach(t -> Hibernate.initialize(t));

    session.close();  
    return transfers;
  }

的HibernateUtil

public class HibernateRepository {

  private static final SessionFactory sessionFactory;

  static {
    try {
            // Create the SessionFactory from standard (hibernate.cfg.xml) 
      // config file.
      sessionFactory = new AnnotationConfiguration().bunchofclasses.configure().buildSessionFactory();
    } catch (Throwable ex) {
      // Log the exception. 
      System.err.println("Initial SessionFactory creation failed." + ex);
      throw new ExceptionInInitializerError(ex);
    }
  }

  public static SessionFactory getSessionFactory() {
    return sessionFactory;
  }

  public static Session openSession() {
    return getSessionFactory().openSession();

但是,我仍然遇到相同的could not initialize proxy - no Session错误。我需要做些什么来正确初始化它?

1 个答案:

答案 0 :(得分:0)

即使你让Find All Method v.2工作,它的编写方式可能会给你带来不好的表现,因为你陷入了臭名昭着的Hibernate N+1 Select problem陷阱。

您应该做的是更改查询以获取会话关闭时需要的集合。

例如,让我们说Item有一个字段Collection<OtherItem> otherItems。你的查询是 from Items as i join fetch i.otherItems

但是请注意,之前的查询不会返回任何不具有Items的{​​{1}}(如果您想要包含这些内容,请使用左连接提取),并且会返回多个相同的如果OtherItems有多个Item的商品。

<强>更新

正如 JBNizet 正确指出的那样,为了解决返回多个OtherItems的问题,您将使用以下查询

Items(或者您将联系抓取包括select distinct i from Items as i join fetch i.otherItems,无论他们是否有Items