I have never done anything with hibernate before. So I am a bit at a loss now...
I want to map a tree structure to my database. The class I use for the tree is WorkItem. It contains an array of childrens (WorkItem). The problem is that, whatever I try, hibernate cannot write a tree to the database.
My WorkItem class (only the hibernate related attributes and operations are shown):
The hibernate mapping contains a lot of settings that I do not understand. It was automatically generated by XDoclets:
The code using the class looks like this:
The execution of this codes results in the following exception:
The same exception occurs, if I do not save and flush the root before adding the child. Even if I do not use a reference to the same class but another one (e.g. WorkItemChild) I get a similar exception with the difference that the SQL update statement contains the WORK_ITEM_CHILD table instead of the WORK_ITEM table.
I have read the hibernate manual and searched the internet up and down but could not find a solution that helps (there have been others with similar problems). Can you help me out?
Thank you very much! [ February 22, 2005: Message edited by: George Kippling ]
I can't help directly with your array issue. The few associations I have in my model are bidirectional one-to-many inverse relationships using Sets.
However, I can give you another option that will also solve a performace problem you'll find if the size of your tree gets large enough (50-100 items). The problem is that to load a tree you have to load the root item (Q1), then all of its children (Q2), then for each child you must load its children (Q3,4,5,...,n), and so on down the tree until each leaf is found. This results in a query for each item.
One way to solve this problem is to load and build the tree in code. First, add a new column to the table: root_id. It should hold the ID of the root item for the tree. To load a tree, load all items with the desired root_id. To build it, simply insert the items into the tree one-at-a-time.
Reducing n queries for an n-item tree to 1 query will save you a considerable amount of time. Since you'll be managing the relationships in code, it would side-step the current issue you're having with Hibernate.
Thank you for the tip. That sounds very useful. However, this project shall serve as an evaluation of hibernate. The performance issue is only secondary (the tree would be loaded at startup only and the server is destined be always online). So, I first want to try to get it running without handling the relations myself. If it really does not work, I will try out your idea.
No worries, I'll help with your situation if I can. I believe the problem is that you are saving the parent and not the new child, but the array mapping tells Hibernate not to save the children when you save the parent:In this case you probably want "all" or "all-delete-orphan", but there are other options.
Thank you for your answers David! You are right, cascade must be set to "all" (or anything else related to creating entries). The above mapping is one of the many settings I tested. The setting cascade="all" results in the same problem.
However, in the meantime I have found out two ways to solve the problem:
1. (the ugly way) Do not save the parent after adding all children, but save the parent and then add and save all children separately.
2. (the way it should be) a) Add unsaved-value="x" to the ID property of the persistent class b) do not forget to initialise the ID property with x c) Add cascade="all" to the array setting The value x must be a value that is cannot be generated by the database. For example, -1 works for "increment".