【问题标题】:Hibernate could not initialize proxy - no SessionHibernate 无法初始化代理 - 没有会话
【发布时间】:2012-11-09 15:41:39
【问题描述】:

我的代码检索与用户相关的所有信息:

SessionFactory sessionFactory = HibernateUtilities.configureSessionFactory();
Session session = sessionFactory.openSession();
UserDetails ud = null;
Set<Address> userAddress = null;

try {
    session.beginTransaction();
    ud = (UserDetails) session.get(UserDetails.class, 1);
    userAddress = ud.getAddresses();
    session.getTransaction().commit();
} catch (HibernateException e) {
    e.printStackTrace();
    session.getTransaction().rollback();
} finally {
    session.close();
}

System.out.println(ud.getName());

for(Address addr: userAddress){
    System.out.println("State " + addr.getState());
}

ud.getAddresses() 只是返回用户的一组Addresses。

我的问题是:为什么即使会话已经关闭,ud 对象仍然具有它的值(例如,名称)? getAddresses()UserDetails 类的实例变量。但是为什么我不能检索它的值,但我可以检索UserDetails 类的常规实例变量?

ud.getAddresses() 是一个@EmbeddedCollection

【问题讨论】:

  • "@EmbeddedCollection" - 你的意思是@ElementCollection

标签: java hibernate persistence lazy-evaluation lazy-initialization


【解决方案1】:

我在 JPA/Hibernate 中遇到了同样的问题,有两种方法可以解决这个问题:

1/默认关闭LAZY,如下:

@Entity
@Proxy(lazy = false)
public class Project {
...
}  

当然,由于性能问题,不推荐这种方式,所以你可以去第二种方式。

2/你可以把@Transactional放在你方法的开头,它可以帮助你保持会话,或者换一种理解,它将会话的职责传递给Hibernate,如下:

@Test
@Transactional
public void testSaveGroup() {
    Department g = new Department();
    g.setName("XDG");
    assertNull(g.getId());
    this.groupRepo.save(g);
    assertNotNull(g.getId());
    System.out.println(g.getId());
    Project dummyPrj = new Project(123L, "KSTA", new Date(), "NEW", "Helm AG", g);
    this.projectRepo.save(dummyPrj);
    // verify
    List<Department> lst = this.groupRepo.findAll();
    Project savedPrj = this.projectRepo.getOne(123L);
    Assert.assertEquals("XDG", savedPrj.getGroup().getName());
}

我的回答迟了,但希望能帮助别人:)

【讨论】:

    【解决方案2】:
    userAddress = ud.getAddresses();
    session.getTransaction().commit();
    for(Address addr: userAddress) {
    

    working with lazy associations 的休眠文档清楚地将这种访问称为错误。只有在会话仍处于打开状态时,您才能与延迟关联的对象进行交互。该部分文档还提供了访问对象的此类惰性关联成员的替代方法,我们更愿意在我们的应用程序中使用的标准中将获取模式指定为 JOIN。

    【讨论】:

    • 所以看起来,我调用ud.getAddresses()的时候其实是在查询数据库?
    【解决方案3】:

    类的所有原始属性都会立即加载,除非您使用字节码增强功能,否则它们不能是惰性的。只有像你的收藏这样真正的关联才会是惰性的。

    【讨论】:

    • 另一个班级怎么样?这被认为是延迟初始化吗?
    • ,如果涉及到 MTO。如果涉及到 OTO,也许
    • 即使会话关闭,我是否仍然可以在 ud 中使用其他实体,假设我有一对多的关系?
    • 几个选项: 1. 立即加载关联 2. 打开另一个会话并通过merge()saveOrUpdate() 附加对象 3. 不要关闭会话(这个非常棘手)
    • 使用 fetch="join" 或在 HQL 中使用连接。或者使用lazy="false"。
    猜你喜欢
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 2020-06-07
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    相关资源
    最近更新 更多