Hibernate could not initialize proxy - no Session
Asked Answered
H

3

15

My code retrieves all information related to the user:

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());
}

The ud.getAddresses() simply returns a set of Addresses of the user.

My question is: why does the ud object still have its value (eg, name) even though the session is already closed? getAddresses() is an instance variable of the UserDetails class. But why can't I retrieve its value but I can retrieve regular instance variables of the UserDetails class?

ud.getAddresses() is an @EmbeddedCollection.

Hopefully answered 21/11, 2012 at 11:34 Comment(1)
"@EmbeddedCollection" - do you mean @ElementCollection?Cutup
A
17
userAddress = ud.getAddresses();
session.getTransaction().commit();
for(Address addr: userAddress) {

The hibernate documentation for working with lazy associations clearly calls out this kind of access as an error. You can interact with lazily associated objects only while the session is still open. That portion of the documentation also provides alternatives to access such lazily associated members of an object and we prefer to specify the fetch mode as JOIN in the criteria used, in our applications.

Altocumulus answered 21/11, 2012 at 11:45 Comment(1)
So from the looks of it, it is actually querying the database when I call ud.getAddresses()?Hopefully
D
20

I faced the same issue in JPA/Hibernate, and there are 2 ways to solve this issue:

1/ Turn off the LAZY by default, as following:

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

Of course, this way is not recommended because of the performance issue, so you can go to the second way.

2/ You can put @Transactional at the beginning of your method, it can help you to remain the session, or another understanding, it pass the duty of session to Hibernate, as following:

@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());
}

My answer is late, but hope to help someone else :)

Duelist answered 3/8, 2016 at 2:9 Comment(0)
A
17
userAddress = ud.getAddresses();
session.getTransaction().commit();
for(Address addr: userAddress) {

The hibernate documentation for working with lazy associations clearly calls out this kind of access as an error. You can interact with lazily associated objects only while the session is still open. That portion of the documentation also provides alternatives to access such lazily associated members of an object and we prefer to specify the fetch mode as JOIN in the criteria used, in our applications.

Altocumulus answered 21/11, 2012 at 11:45 Comment(1)
So from the looks of it, it is actually querying the database when I call ud.getAddresses()?Hopefully
K
4

All the primitive properties of the classes are loaded right away, they can't be lazy unless you're using bytecode enhancements. Only real associations like your collection can be lazy.

Krugersdorp answered 21/11, 2012 at 11:59 Comment(6)
how about another Class? is that considered a lazy initialization?Hopefully
Yes, if it comes to MTO. And maybe if it comes to OTO.Krugersdorp
Is there anyway I can other entities inside the ud even though the session is closed, let's say I have a one to many relationship?Hopefully
Several options: 1. Load associations right away 2. Open another session and attach the object back by merge() or saveOrUpdate() 3. Don't close the session (this one is very tricky)Krugersdorp
how do you load associations?Hopefully
Using fetch="join" or using joins in HQL. Or using lazy="false".Krugersdorp

© 2022 - 2024 — McMap. All rights reserved.