Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Hibernate entity referencing itself by foreign key

 
Kjeld Sigtermans
Ranch Hand
Posts: 127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Let's say I have a table called Entity having a database managed identity column 'id'. It also has another column called 'parentId' having a foreign key constraint to 'its own' Entity.id. This way I'd like to create a parent/child relationship between Entity rows.

I have generated a class Entity that represents the Entity table. The FK reference is represented by Entity.setEntity(Entity p) where p is the parent.
When creating a new child entity Entity c = new Entity() I want to have c be its own parent so I set c.setEntity(c).

When trying to persist c, Hibernate complains: org.hibernate.PropertyValueException: not-null property references a null or transient value.
It is obvious the parent I try to set is not yet persisted (because it is c) and therefore it has no id, but I was hoping Hibernate would be able to deal with this in some smart way, maybe by temporarily turning off auto identity on the id column or nullability on the parentId column.

Of course I can remove the FK constraint which creates Entity.setParentId(int) instead of Entity.setEntity(Entity), or probably temporarily turn off the column properties myself. But is there a better way to achieve this goal?

Thanks,
Kjeld
 
Victor Dolirio
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can do something like the following code snippet:



I hope to help.

[]s
 
Kjeld Sigtermans
Ranch Hand
Posts: 127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Victor but I already have (generated) Entity classes and mappings and I explicitly use native id generation. I don't see how GenerationType.AUTO will do the trick? The problem isn't so much how to set up the class, but I was hoping Hibernate was able to deal with not-yet-persisted entities that refer to themselves by property.
Meanwhile I have made the parentId column nullable. First I persist all entities with parent = null, then I assign the correct parent to each entity and I persist them again. (saveOrUpdate). It is a two phase process and I don't like the concession of making the column nullable, but this does the trick.

Cheers!
 
Victor Dolirio
Ranch Hand
Posts: 57
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My apologies, I confess that I don't have undertood correctly your question, but now, with a better read I've got a better understand. IMO, isn't it is a paradoxical concept?? How could one element it self be your own parent? This is worst than "Which came first, the chicken or the egg?". But regardless of my humble opinion, I think that you can accomplish this in two steps: first, saving the entity without parent (to have the hibernate make the identity of the entity) and then update this entity supplying the parent entity to it self. I don't know if that is possible to do it in a single step.

For sake of curiosity, which is the reason that towards you to have a element being a parent to it self?

best regards.
 
John Bengler
Ranch Hand
Posts: 133
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Kjeld,

if you use a two step operation,why don't you first persist the "master Entity" and then the one which holds alink to the master entity?

But I understand your problem and think it should workin one persist operation...


John
 
John Bengler
Ranch Hand
Posts: 133
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi again,

thinking a second time about your problemI think it is clear that you have to define the foreign key column nullable..

Beacause either you build a huge "ring" of Entity entries or you will have at least one entry without a parent...

Or is this the reason why you want to have one entry to be its own parent?

Sorry, I think I just recognized that your problem occurs when your using such a self-reference...


But I still think it should be possible for Hibernate to handle this correct...


John
 
Kjeld Sigtermans
Ranch Hand
Posts: 127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Victor, John, thanks for your thoughts about this.
The reason I want an entity to be able to refer to itself is basically because it is a business requirement, and I must say I've seen it before. For example, in an insurance context, think of a person A who is responsible for the payment behaviour of others, B and C. He (or she) would be his/her own 'parent', as well as the 'parent' the 'children' refer to. I.o.w. A being responsible for A, B and C. Maybe the word 'parent' is a little confusing in this context.
Yes, I have now made entity.parentId nullable, but I don't want this (BReq says everybody must have a 'parent' and now I have broken this req to be able to solve my problem). Plus I want to make sure technically that a 'parent' can never be omitted.
Also it should be feasible to store the entity in one go, not two-step, but I'm not sure if it's possible using Hibernate either.
Thanks!
 
Victor Dolirio
Ranch Hand
Posts: 57
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Kjeld, IMO hibernate by itself ain't the problem. Think in your dbms side: is it possible to insert a new record this way without violate the FK constraint? Maybe is possible if your dbms use sequences, you can get the sequence before insertion and set up both field of you bean: id and 'parent' reference. Just map your bean to have indetity controled by you and you can write a interceptor to get next value from sequence and fill the fields. Its just a suggestion.

hope be helpfull...
 
Kjeld Sigtermans
Ranch Hand
Posts: 127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes you are right, Hibernate is not the problem, the problem is as fundamental as the data design. However, I was hoping Hibernate would provide a little trick to be able to deal with this. Maybe by quickly make the column nullable, insert the entity, update it with its parent, and change the column back to not-nullable. Oh well, maybe one can't expect Hibernate to do magical stuff on such an underlying design.
For now I have accepted the nullable column and two-phase persisting of Entity and I moved on.
 
John Bengler
Ranch Hand
Posts: 133
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Victor Dolirio wrote: Maybe is possible if your dbms use sequences


I'm using an Oracle database and when you enable SQL Output you can see that for generated Ids Hibernate first selects the next value from the mapped sequence and performs the insertin a second step - so I don't see a problem why Hibernate should not be able to use this selected value for the primary key and for the foreign key..

But of course I don't know what kind of database Kjeld uses and how Hibernate handles the genertion of keys for this..
 
Kjeld Sigtermans
Ranch Hand
Posts: 127
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Interesting. Well I use SQL Server 2005 and I chose 'native' generation of ids, so SQL Server generates the id.
Cheers K
 
Lalit Narayan Mishra
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Found a nice book on Spring & Hibernate. Have a look at this blog...

http://amritendude.blogspot.in/2014/06/new-book-on-spring-4-and-hibernate-4.html
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic