Fetching Collections Puzzle

#1

I am working on a project where I need to travel through a massive graph of objects. One of the main entity is the Node which is shown below.

class Node {
    Node parent
    List<Node> children
    Node rightSibling
    Node leftSibling
    int rank
}

I have the following issues/doubts

  1. If I dont declare explicitly the fetch strategy for "children" as FetchType.Eager, then how can I retrieve the Nodes stored in this list. Because no matter what I try, if I dont declare the FetchType to Eager, the children field of all my retrieved nodes are of size zero
  2. When I declare the FetchType as Eager, then isn't the database actually retrieving the whole graph stored in the database, considering that every Node in my graph is at some level descendant of the root Node.

I have been looking for an optimum persistence solution for my project for quite some time now. I have tried every combination of ORM and RDBMS but they are just not cut out for this kind of work. I also tried DB4O but it leaves a lot to be wanted. ObjectDB was a pleasant surprise until I got stuck with this problem. I would be indebted to you if you could solve this sticky situation.

 

#2

When a Node object is retrieved from the database - the children field is expected to hold a proxy list (e.g. objectdb.java.util.ArrayList, which extends java.util.ArrayList).

In the debugger the proxy list might look empty - but as soon as your application accesses its content (e.g. by invocation of the size method) it is filled automatically. Unless the Node object is detached, for example if the EntityManager is already closed.

As you wrote - if the children list is annotated as EAGER - the entire tree will be loaded from the database. Notice also, that the rightSibling and leftSibling fields are EAGER by default. They will be loaded lazily only if they are annotated as LAZY explicitly and enhancement is used (which is recommended anyway to improve performance).

ObjectDB Support
#3

Paul,

 

As posted above your collection should be initialized as soon as you try to get the children for example children.get(0) will cause the proxy to go and retrive the first element of the collection. This will only work if you are within a transaction. (I usually do not start a transaction unless i am adding, or modifying elements in the db)

 

By default JPA spec says that  colletions are to be lazy fetched. You can try this in a query. 

"select n from Node n left outer join fetch n.children where ....." this will also fetch your collection.

Basically you can use the default fetch strategy and use the query I mentioned when you need the collection, or use a transaction to lazily initilize . Note that JPA spec if i recall correctly does not specify the number of collections you can fetch through a query but in practice  I have only been able to retreive one. (I am talking about hibernate and other orm, I have not tried this through ObejectDB, it might work for multiple here.)

 

Erick

#4

Thankyou so much ! It seems my search for the perfect tool is over.smiley I wish you and your team great success. Thank you once again. 

#5

Thanks Erick,

I was messing up with the EntityManagers, which was the root of the problem.

Have a beautiful day !

Reply