Ah, then we are a few months too late in posting our code then =] Good to hear that it will eventurally come to Hibernate - until then, we'll use our system.

However our graph loader has come up a rather obscure hibernate bug you may wish to look into to.

Lets say I have 3 classes, A, B, C, that are lazy (proxies), and have collections that are lazy as well:

A has a many-to-one property to B
A also has a collection (many-to-many or one-to-many) of Cs.
C has a collection (again many-to-many or one-to-many) of Bs

If I wished to load object A, it's collections of Cs, and for every C in that collection its collections
of Bs - leaving the B property of A uninitialized - then we would issue the following optimized hibernate queries in the same session to do so:


select A from A left join fetch A.C;
select C from A join A.C left join fetch C.B;

Hibernate should detect the second load in the session and link all of the objects together, thus completing our graph.

This is where the problem occurs. If the uninitialized proxy of B has the same id as any B in the B collections we loaded for C, then those B objects in the C collections will also be uninitialized (proxy initialization exception), even though we explicitly asked for them to be initialized.

Now a real life situation to make it more clear. If A is "cat", B is "owner", and C is "kittens", a "cat" would have a "owner" property and a collection of "kittens", but then each kitten could have an owner as well. In order to load a particular cat, its kittens, and the owners for those kittens we would:

begin session;

select Cat from Cat left join fetch Cat.kittens;
select kittens from Cat join Cat.kittens kittens left join fetch kittens.owner;


end session;

The problem: if the cat we loaded had owner_id = 10, then any kitten that has an owner_id = 10 will not have its owner initialized! The fix would be either to re-design your database or to explicitly load the owner for the cat as well:

begin session;

select Cat from Cat left join fetch Cat.kittens left join fetch Cat.owner;
select kittens from Cat join Cat.kittens kittens left join fetch kittens.owner;


end session;

Any thoughts?

----- Original Message ----- From: "Gavin King" <[EMAIL PROTECTED]>
To: <hibernate-devel@lists.sourceforge.net>
Sent: Thursday, February 10, 2005 12:08 AM
Subject: RE: [Hibernate] Is it worth contributing this code or posting it somewhere?



Correct. This is a current limitation that will be solved “soon”. Meaning right after 3.0 final release. Its fairly straightforward.

------------------------------------------------------------------------

*From:* [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] *On Behalf Of
*Jordan Laughlin
*Sent:* Thursday, 10 February 2005 6:46 PM
*To:* hibernate-devel@lists.sourceforge.net
*Subject:* RE: [Hibernate] Is it worth contributing this code or posting
it somewhere?

Hello, I just wanted to jump in because I'm really not clear on how the
queries produced could result in a cartesian product. Since every level
of the graph contains an on clause that references the table before it,
each level of the tree is limited (by its particular join type) and the
amount of results returned at each level will be the amount of rows in
the largest subset that meets its join condition.

For instance,

[SQL QUERY]

Select * from A join B on A.id = B.id join C on C.id = B.id join D on
D.id = C.id left join E on E.id = D.id

This is exactly what our queries do: this does not result in a cartesian
product, it returns at a maximum the number of rows in the largest table
that meets a join condition. Now in each of our queries we may join any
number of properties by left join since we know each join will return
only one row (criteria does this as well). The cartesian product would
show its ugly head if we instead attempted to load multiple collections
per query,* **which is not what we are doing*: instead we are doing one
query per collection.

For instance, if we wish to load A, its B* **property*, and the
collections C and D of property B, we would issue two different queries:

[HIBERNATE QUERIES]

Select A from A left join fetch B on A.id = B.id left join fetch C on
C.id = B.id;

And

Select B from A left join fetch B on A.id = B.id left join fetch D on
D.id = B.id;

Since B is a property, it's left join returns only one row. By issuing
the above queries in order in the same session, we get A, it's B
property loaded, and the collections C and D for the B in A fully loaded.

As far as we know Hibernate currently does not allow for object graph
loading (loading a collection of a collection, etc.). The purpose of our
code was to do that: if you can suggest a better way of doing this, or a
way to split up the above queries when loading the graph, which avoids
n+1 selects, please point us to the documentation.

Thanks,

Jordan

-----Original Message-----
From: Adrian Ridner [mailto:[EMAIL PROTECTED]
Sent: Wednesday, February 09, 2005 8:16 PM
To: 'hibernate-devel@lists.sourceforge.net'
Cc: [EMAIL PROTECTED]
Subject: Re: [Hibernate] Is it worth contributing this code or posting
it somewhere?

On Feb 7, 2005, at 9:17 PM, Christian Bauer wrote:



On Feb 7, 2005, at 11:08 PM, Adrian Ridner wrote:



> Did we miss something? I'll be optimistic and hope we didn't reinvent

> the wheel, but if we did, it was a fun exercise :)



Read up on the docs some more. What you try to do would create a

Cartesian product and be slower than two queries (which is what you

discovered will happen). This is documented in every other place and a

sensible limitation. You can write a custom SQL query in very special

cases, if you are sure the product is faster than two queries.



Thanks for the reply. Sorry I didn't see it before, it got lost in my

mailbox. I appreciate your feedback. I guess that answers my original

question. We'll read up the docs more to see if we find anything. I am

wondering if I didn't communicate what we are doing correctly though,

because we are running this on tables with 5,000,000 rows each, and it

is faster than anything else we tried.

In any case, thank you for a great product!

Adrian

--
Gavin King
+61 410 534 454
+1 404 822 8349
callto://gavinking

Hibernate
[EMAIL PROTECTED]
http://hibernate.org

JBoss Inc
[EMAIL PROTECTED]
http://jboss.com



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_ide95&alloc_id396&op=ick
_______________________________________________
hibernate-devel mailing list
hibernate-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/hibernate-devel



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_ide95&alloc_id396&op=click
_______________________________________________
hibernate-devel mailing list
hibernate-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/hibernate-devel

Reply via email to