This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Object Relational Mapping and the fly likes Hibernate Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "Hibernate" Watch "Hibernate" New topic
Author

Hibernate

Patrick McDonogh
Ranch Hand

Joined: Oct 13, 2005
Posts: 89
Hi all,
I was looking for a hibernate forum but could not find one so if this is posted in the wrong forum please let me know.

I keep getting an error saying that hibernate can not lazy initialize my collection as the session doesnt exist or was closed.

For instance say i have an object Person.

class Person {
String fname = null;
Collection addresses = new ArrayList();
}

The addresses collection is then mapped to addresses in the address table for example.

Then say i run the following code i get the lazy exception on the "Collection c = p.getAddresses();" line in the getAddresses method.

class Test() {
public static void main(String[]args) {
long id = 1;
Person p = getPerson(1);
Collection addresses = getAddresses(p);
}

private getPerson(Long id) {
Session s = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
List results = session.get("from Person where id = " + id).list();
tx.commit();
session.close();
return results.get(0);
}

private getAddresses(Person p) {
Session s = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
Collection c = p.getAddresses();
tx.commit();
session.close();

}
}

Please note i have greatly simplified the actual code and as a result it may not compile as i may have typed something incorrectly but it does get the exact problem across.
I can see that somehow before the "Collection c = p.getAddresses();" line i have to some how associate the passed in Person p variable with the created session in the method session.
How is this done in hibernate?

Please note that i would rather not have to run another query to get the Person again(Using the passed in persons id or something) and then get their addresses, as this adds a performance overhead i would rather miss out.

Surely there is a method that does something like session.magicallyUseThisSessionForThisObject(Object o) or something.

Thank you for any help and guidance.

Cheers,

Patrick
Jaikiran Pai
Marshal

Joined: Jul 20, 2005
Posts: 9912
    
158

I was looking for a hibernate forum but could not find one so if this is posted in the wrong forum please let me know.


We have a separate forum for Hibernate and Other ORM tools


class Test() {
public static void main(String[]args) {
long id = 1;
Person p = getPerson(1);
Collection addresses = getAddresses(p);
}

private getPerson(Long id) {
Session s = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
List results = session.get("from Person where id = " + id).list();
tx.commit();
session.close();
return results.get(0);
}

private getAddresses(Person p) {
Session s = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
Collection c = p.getAddresses();
tx.commit();
session.close();

}
}


Hibernate 3 by default does not load the collections (lazy loading). It waits until you *touch* the collection for the first time to load it. And when it tries to do so, it expects the session to be open so that it can load the object from the database by firing queries.

In your case, the collection (addresses) is not loaded when you retrieve the Person in the getPerson method. Then when you invoke the getAddresses method on the Person object, it tries to load the addresses by querying the database. But since you have closed (session.close) the session in your getPerson method, it wont be able to load this addresses collection.

You could change the code to look like:



Let the session remain open till you get the addresses.

P.S.: This is just a pseudo-code.


[My Blog] [JavaRanch Journal]
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by Patrick McDonogh:
...
I can see that somehow before the "Collection c = p.getAddresses();" line i have to some how associate the passed in Person p variable with the created session in the method session.
How is this done in hibernate?
...


Well it depends. Best is to look in the documentation. I'll give it a shot though...

Since your object p was detached, and used outside of the session you must reassociate it like so;

session.lock(p,LockMode.NONE);

This assumes the object's persistent fields have not been modified, AND that no other instance of this object (with respect to the database row) is in the current session. If this object is already in the session for whatever reason you will need

session.merge(p);


See the reference documentation section 10.6. Good Luck.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Hibernate
 
Similar Threads
Retrieving request parameters (from the url) in a jsp page
Assigning values to a returned object from query
Need help with Hibernate Query language - timestamp field
Problem with inserting new data into database using hibernate
StaleStateException