File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Object Relational Mapping and the fly likes retrieving object hierarchy - many-to-one? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "retrieving object hierarchy - many-to-one?" Watch "retrieving object hierarchy - many-to-one?" New topic
Author

retrieving object hierarchy - many-to-one?

Vinnie Jenks
Ranch Hand

Joined: Apr 26, 2004
Posts: 207
I'm just a beginner and I'm having some trouble understanding a couple of concepts in Hibernate for which I think are pretty basic in OOP and relational data.

Let's say I have a class w/ several properties and one of those properties is an ArrayList of objects. Can this object be mapped to a one-to-many table relationship in the database so all of those objects can be retrieved at once?

Inversely, can they be saved this way into the database in a recursive manner?

For example...if I have a class User which has a an accessor method of getAddresses, which retrieves a List of Address objects. Can I map these objects to the User and Address tables and retrieve the User and Address data in one Hibernate "query" w/o having to get each of them manually. And, likewise, could I session.save(User) after having populating the addresses property w/ a List of Address objects...w/o having to do them separately?

I just bought Hibernate In Action last night and have been flipping through it...and I don't see a real clear example or explanation of this concept. I see that many-to-one relationships can be created but is this strictly for referential integrity, cascading, etc.?

Thanks!
Lewin Chan
Ranch Hand

Joined: Oct 10, 2001
Posts: 214
Doesn't the hibernate on-line documentation discuss exactly that? I think it goes on about Cats having Kittens and the like. This is an example that I've recently worked on (names changed to protect the guilty)
Now, my database structure is like this (This was designed by the DB guy, so I had to map hibernate onto the database structure).



then you could have a mapping in Parent of

And a mapping in Child of


i.e. the Child controls the relationship to the parent, but the Parent class contains a Set of Child elements. i.e.



Which results in java code using the hibernate session thus:



So yes, you can do it all in the mapping, but it really depends on how you want the relationship to work. I suspect for your example (User/Addresses), then Address would be the child element, and User is the parent.

You can use lazy=true, lazy=false in some of the elements, to control whether you do lazy loading or not. Injudicious use of lazy=false may cause performance problems (i.e. you have a situation where you inadvertently load up the entire db into memory).

Hope that helps
Lewin
[ September 14, 2005: Message edited by: Lewin Chan ]

I have no java certifications. This makes me a bad programmer. Ignore my post.
Vinnie Jenks
Ranch Hand

Joined: Apr 26, 2004
Posts: 207
OK - it's been a few days and I did my homework - thanks for the point in the right direction.

By all accounts I think I'm doing it right but cannot get it to work - it seems that Hibernate is not *at all* intuitive and I'm very familiar w/ SQL and relational databases.

Here's where I'm at, maybe you can tell me where I went wrong:

I've got two objects w/ a "one-to-many" parent/child association, real simple stuff. I am trying to select the parent and automatically select the children - all of this is defined in the two mapping *.hbm.xml files of the two classes - all cobbled together from the Hibernate doucmentation and the examples found in Hibernate in action, which I purchased last week.

Here my two classes. AttributeCategory is the parent and Attribute is the child - an AttributeCategory can have many Attributes...which is defined as a List in the AttributeCategory class...see below:





Here are my AttributeCategory and Attribute hbm.xml files, respectively:





My call to retrieve a list of AttributeCategory objects (with nested Attribute lists in each) is too dispersed amongst app layers to provide all the code but rest assured, I'm able to call unrelated lists just fine the same way - I'm only getting an error when trying to go beyond a single map-to-class in the mapping files. The error I'm getting is:



The session is most definitely not closed - like I said, I'm using the same boilerplate HibernateUtil from Caveat Emptor all over this application and it works fine as long as I'm only mapping one class to one mapping file...this is the only case I get a "session closed" problem.

I posted this w/ no answers on the Hibernate forum. I found another fellow there who's got the same problem in another post and his "solution" was to not close the sessions after querying data...but that would lead to connection pool leaks which would eventually cause an exception to be thrown when the pool "runs dry."

Any advice? Thanks!
Lewin Chan
Ranch Hand

Joined: Oct 10, 2001
Posts: 214
Hej

Just you and me having a discussion about hibernate eh. There's not much wrong with your code as far as I can see, it's almost exactly the same as the example I posted (and that's working for me)

Here's some things that may point you in the right direction. A thing to note is that the "List" in AttributeCategory is probably a org.hibernate.PersistentList (or whatever). This is the thing with the reference to the session.

a) If you haven't implemented hashCode and equals in Attribute / AttributeCategory then do that right now . I've been re-reading some of the hibernate docs this week, and I remember mention of the fact that you have to do that if you want to use detached sessions (i.e. if you want to pass the object through many app layers ).

b) Are you by any chance using XMLEncoder with the hibernate object because they don't play nice unless you have your own persistence delegate.

c) Write a test case for it. The reason I'm suggesting this, is you can use hibernates hbm2ddl.auto feature to auto-create a inline memory database using HQL (e.g.)


Then add log4j.properties such that
log4j.category.org.hibernate.tool.hbm2ddl=DEBUG

So that you can see the schema export. That'll tell you if there's any erros in your hibernate config vs your actual schema
[ September 23, 2005: Message edited by: Lewin Chan ]
Vinnie Jenks
Ranch Hand

Joined: Apr 26, 2004
Posts: 207
Lewin, you're the best, I can't tell you how much I appreciate the help.

Before I get too far into what you've told me - let me show you the test project I've setup as a test-case. I took my example from the previous post and put it into a single, simple web project w/ a single servlet.

Here's the doGet from my servlet (ORMUtility is HibernateUtil from Caveat Emptor, I just renamed it to protect the innocent):



Here is AttributeCategory and Attribute, respectively:





...and the corresponding hbm.xml files:

AttributeCategory.hbm.xml...



Attribute.hbm.xml...



The queries that are spit out:



My full stack-trace w/ log4j output...


So, to simplify what happened here - I got the AttributeCategory record but did not get the Attribute records (Attributes List in AttributeCategory is null) *EVEN* though both of the queries being generated by Hibernate are correct! I bolded TestSession (the servlet) line 43 at the beginning of the post...it's the nested loop where I try to print the value of an Attribute from the collection...which is obviously null.

SOOOO...with all that being said...on to what you've stated in your last post.

I use the java.util.List for nearly all of the collections in my object model...would I have to swtich them all to org.hibernate.PersistentList!?


a) If you haven't implemented hashCode and equals in Attribute / AttributeCategory then do that right now . I've been re-reading some of the hibernate docs this week, and I remember mention of the fact that you have to do that if you want to use detached sessions (i.e. if you want to pass the object through many app layers ).


I'm not sure I follow this? Each class in my object model should have an unique hashCode value? I'm having a *very* serious problem passing the session through my app layer...session management has been a total nightmare for me so far. To break my app down I've got the following layers in my real app, which I'm trying to work through:

1. Presentation (Servlet, dispatching to a JSP ala MVC)
2. Facade (Small class library to sheild presentation from back-end)
3. "Framework" Layer (Object model, Hibernate)
4. Database (MS SQL 2000)

All three are cleanly separated. The presentation layer makes a call to the Facade to get objects. The facade calls the "Framework" layer, through encapsulation (open() and close() methods in facade).

Sessions have worked great this way until I tried to do the one-to-many join between these two objects. Otherwise, mapping one object to one table never caused a problem w/ sessions!

So, if setting a hashCode value to my object model classes will help w/ detaching form the session...that may be the magic cure for this issue!

I'm not using XMLEncoder, that I'm aware of?

Thanks Lewin!!
[ September 23, 2005: Message edited by: Mark Spritzler ]
Lewin Chan
Ranch Hand

Joined: Oct 10, 2001
Posts: 214
Hey,

Your error appears to be a NullPointerException (from the test case).
Now, I'm not worknig with 1.5 specifically, so I'm curious as to why it would happen on line 43 rather than the for line. From the code the only thing that could cause the NPE is the ac.getAttributes() (i.e it returns null, so you can't iterate over it). My question is, if you were to write



does the line of the error change?

I'd probably put some null protection in regardless into the AttributeCategory class.


Regarding equal + hashcode(). I'm referring back to the Hinberante3 documentation section 5.3 -Implementing equals and hashcode() where it says

You have to override the equals() and hashCode() methods if you

* intend to put instances of persistent classes in a Set (the recommended way to represent many-valued associations) and
* intend to use reattachment of detached instances

Hibernate guarantees equivalence of persistent identity (database row) and Java identity only inside a particular session scope. So as soon as we mix instances retrieved in different sessions, we must implement equals() and hashCode() if we wish to have meaningful semantics for Sets.


You're using java.util.List, but I think you actually want to use Set (as each Attribute == a database row, and they must therefore be unique).

Re: PersistentList vs List. - I think you maybe misunderstood me here, using java.util.List is fine. But bear in mind that the actual list implementation that will be used by hibernate will be a PersistentList rather than one of the vanilla java.util.ArrayList/Vector. A PersistentList is one that contains a reference to the session so the objects can be updated (from how I read it).
Lewin Chan
Ranch Hand

Joined: Oct 10, 2001
Posts: 214
Just so you can do a compare and contrast comparison here's a couple of (real life) files, package names removed to keep my current employer's identity secret . You might want to ask why they want me to write a "calendar application" but when the client says jump, the contractor says it'll cost you this much.





So it's a classic bi-directional many to one mapping. Many job executions to a single calendar entry. You'll notice that I'm not using fetch="join" or index-column, I'm not entirely sure why, I do know that fetch="join" broke a few of my test-cases with regards to object deletion.

Here's the actual beans themselves (some code removed for the sake of brevity)



And my tables are - I probably wouldn't have designed the DB like this, but it was already in place...



Other than this, I really don't know how to help you.

L

[ September 26, 2005: Message edited by: Lewin Chan ]
[ September 26, 2005: Message edited by: Lewin Chan ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: retrieving object hierarchy - many-to-one?