This week's book giveaway is in the Agile and Other Processes forum.
We're giving away four copies of The Little Book of Impediments (e-book only) and have Tom Perry on-line!
See this thread for details.
Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

JPA and a parent children relationship in a tree data structure

 
Kenneth Gustafsson
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I've got a tree structure of TreeNode's:

The TreeNode class is an JPA entity and in their class definition we can find:


In this application getParent() will be called a lot while getChildren() will be called fairly seldom. It should also be added that the tree structure will become fairly large, around 5000 nodes.

At run time we will get TreeNodes using their id and perform operations on them. The order will be to start at a leaf and then loop through the parents until we reach the root node. 99.99999% of the time we will only read data from our tree of TreeNode's.

If we use FetchType.EAGER for the children we'll get the entire tree each time. Which seems like a horrific scenario.

Our second option is to use transactions which enables us to use use FetchType.LAZY. But we're mostly reading and there will be lots of concurrent readnig going on. Is that a good idea or will it block performance?

The third option is to write getChildren() as a separate method. And use a query to lookup and return the children. In that case we won't have any instance variable containing a list of children at all. But it's not needed often anyway.

Which way do you prefer? Or do you have different suggestion?
[ May 08, 2008: Message edited by: Kent Larsson ]
 
Cameron Wallace McKenzie
author and cow tipper
Saloon Keeper
Posts: 4968
1
Hibernate Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In this application getParent() will be called a lot while getChildren() will be called fairly seldom. It should also be added that the tree structure will become fairly large, around 5000 nodes.



So, let's not make the fetch type eagar for children. That's my instinct if getChildren is not called often. Thoguhts?


At run time we will get TreeNodes ... 99.99999% of the time we will only read data from our tree of TreeNode's. If we use FetchType.EAGER for the children we'll get the entire tree each time. Which seems like a horrific scenario.


I'm definitely horrified! Especially if it's a large tree structure.

What inheritance type mapping are you using? Is this a concern? Sounds like alot of joins if you use anything but SINGLE_TABLE. That's my gut instinct.

Here's a little tutorial I put together on inheritance mapping strategies with Hibernate and JPA. It talks about the benefits and drawbacks of InheritanceType.SINGLE_TABLE, InheritanceType.JOINED and InheritanceType.TABLE_PER_CLASS.

How to Perform Inheritance Mapping with Hibernate and JPA (Java Persistence API) Annotations





Gavin King (or was it Christian Bauer?) gets all upset when people talk about reading from a database without being in the scope of a transaction. You always need a transaction, don't you?

As far as performance goes, I think this node structure will definitely make any approach resource intensive. Looping through a deep set of leaf nodes is never a streamlined process.

I like a fetch type of lazy, with the process done within a transaction. I'd be curious to the number of transactions, and the expected length of the transaction.

-Cameron McKenzie
[ April 23, 2008: Message edited by: Cameron Wallace McKenzie ]
 
Kenneth Gustafsson
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for your nice and informative reply!

To clearify a bit, even though I think you understood me, it's always nice to be clear and I feel I could improve on my previous post. :-)

The tree structure I'm talking about uses aggregation, not inheritence. Which means that it's a tree structure of entity instances.

So, let's not make the fetch type eagar for children. That's my instinct if getChildren is not called often. Thoughts?

Then I'll have to do things inside a transaction. Which might be a problem.

My original plan was to retrieve the correct TreeNode entity and store it as a session object. Then I'll show a web page with some information about the TreeNode. Next the user performs various actions on the object instance which is temporarly stored in the session. When the user has made all the modifications (s)he wants the TreeNode is updated in the database. Between retrieval of the TreeNode and update there are several calls between JSP's and Servlets.

As you can see using transactions isn't a possibility with the above approach. Is the above approach bad? Would it be better to use for example a stateful session bean?

Gavin King (or was it Christian Bauer?) gets all upset when people talk about reading from a database without being in the scope of a transaction. You always need a transaction, don't you?

If I'm only reading. Why would I need to be inside a transaction then? I'm pretty new to databases but I asked my collegues and they didn't know a reason for being in a transaction while only reading either. I'm all eyes and would very much like to know.

What inheritance type mapping are you using? Is this a concern?


I don't think it's a concern as this structure isn't using inheritance yet. In our real world scenario some TreeNode's will have extended information, let's call them HaikuTreeNode's. They will hold methods for interacting with their Haiku information as well. But I don't think it's relevant.
 
Mark Spritzler
ranger
Sheriff
Posts: 17278
6
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
"If we use FetchType.EAGER for the children we'll get the entire tree each time. Which seems like a horrific scenario."

You would only be able to set just one of those one-to-many relationships as eager anyway. If you set two, then you would get a cartesian product, because it will use a left outer join.

Anyway, there are also other fetch modes that might interest you, I think they are also in JPA. But hibernate has "subselect", which basically makes only one more query per relationship. So if you call getChildren() on one of them, then it will go to the database with one query to fill up the children. It is called subselect because that second query has the first query as a subselect in it so it just brings back the children for the one parent.

Transactions are required.

Mark
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic