Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate could not initialize proxy - no Session

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.

like image 622
KyelJmD Avatar asked Nov 21 '12 11:11

KyelJmD


People also ask

Can't initialize proxy no session Hibernate Java?

We have seen that this error mainly comes when you have closed the connection and trying to access the proxy object which is no fully initialized. Since Proxy object needs a connection, you can either reattach object to the session or carefully avoid writing such code, which access uninitialized Proxy object.

How do I fix Hibernate LazyInitializationException?

The right way to fix a LazyInitializationException is to fetch all required associations within your service layer. The best option for that is to load the entity with all required associations in one query.


2 Answers

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 :)

like image 59
doannx Avatar answered Oct 09 '22 17:10

doannx


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.

like image 35
Vikdor Avatar answered Oct 09 '22 16:10

Vikdor