Java Hibernate无法初始化代理-无会话

Java Hibernate无法初始化代理-无会话,java,hibernate,persistence,lazy-evaluation,lazy-initialization,Java,Hibernate,Persistence,Lazy Evaluation,Lazy Initialization,我的代码检索与用户相关的所有信息: SessionFactory sessionFactory = HibernateUtilities.configureSessionFactory(); Session session = sessionFactory.openSession(); UserDetails ud = null; Set<Address> userAddress = null; try { session.beginTransaction(); u

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

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());
}
SessionFactory SessionFactory=HibernateUtilities.configureSessionFactory();
Session Session=sessionFactory.openSession();
UserDetails-ud=null;
设置userAddress=null;
试一试{
session.beginTransaction();
ud=(UserDetails)session.get(UserDetails.class,1);
userAddress=ud.getAddresses();
session.getTransaction().commit();
}捕获(休眠异常e){
e、 printStackTrace();
session.getTransaction().rollback();
}最后{
session.close();
}
System.out.println(ud.getName());
for(地址addr:userAddress){
System.out.println(“State”+addr.getState());
}
ud.getAddresses()
只返回用户的一组
地址

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

ud.getAddresses()
是一个
@EmbeddedCollection

userAddress = ud.getAddresses();
session.getTransaction().commit();
for(Address addr: userAddress) {

的hibernate文档清楚地将这种访问称为错误。您只能在会话仍处于打开状态时与延迟关联的对象进行交互。文档的这一部分还提供了访问对象的此类延迟关联成员的替代方法,我们更愿意在应用程序中指定获取模式作为所用条件中的联接。

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

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

1/默认情况下关闭“惰性”,如下所示:

@Entity
@Proxy(lazy = false)
public class Project {
...
}  
@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/您可以将@Transactional放在方法的开头,它可以帮助您保持会话,或者另一种理解,它将会话的职责传递给Hibernate,如下所示:

@Entity
@Proxy(lazy = false)
public class Project {
...
}  
@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());
}
@测试
@交易的
public void testSaveGroup(){
部门g=新部门();
g、 设置名称(“XDG”);
assertNull(g.getId());
此.groupRepo.save(g);
assertNotNull(g.getId());
System.out.println(g.getId());
项目dummyPrj=新项目(123L,“KSTA”,新日期(),“新”,“赫尔姆公司”,g);
这个.projectRepo.save(dummyPrj);
//核实
List lst=this.groupRepo.findAll();
Project savedPrj=this.projectRepo.getOne(123L);
Assert.assertEquals(“XDG”,savedPrj.getGroup().getName());
}

我的回答很晚,但希望能帮助其他人:)

所以从外观上看,当我调用ud.getAddresses()时,它实际上是在查询数据库?另一个类如何?这被认为是延迟初始化吗?是的,如果涉及到MTO。如果涉及到OTO,我是否可以在ud中创建其他实体,即使会话已关闭,比如说我有一对多关系?几个选项:1。立即加载关联2。打开另一个会话并通过
merge()
saveOrUpdate()
3将对象附加回。不要使用fetch=“join”或在HQL中使用连接来关闭会话(这是一个非常棘手的问题)。或者使用lazy=“false”。@EmbeddedCollection”-您的意思是
@ElementCollection