I have an entity called "Document" which has a many-to-one relation to the entity "Client". But on the Client side the relation to Document is one-to-one since I only want to save a reference to the latest Document.
My problem now is this: First I want to create and persist a new Document including a reference to a Client, which works.
But then I want to set the "Document" reference in Client to point to the new Document. This works when I step through the java code but when I check the contents of the database later I find that the Client record in question still points to an old Document and not the new one.
I'm getting no errors. It just seems like that Client instance doesn't get updated in the db. What can be the reason for this?
I can add that I'm closing the Session through a filter and when I stepped through the code I saw that this happens after the relevant code has been executed (at least it looks that way), so that seems alright.
Maybe the problem is due to my Hibernate mapping files since I'm not absolutely sure I've written them correctly. Therefore I'm pasting the most relevant parts of them here:
<hibernate-mapping> <class name = "BusinessLogic.Entities.Document" table="document"> ..... <many-to-one name = "client" column = "clientId" foreign-key= "clientId" class = "BusinessLogic.Entities.Client" cascade = "save-update" fetch = "join"/> ..... </hibernate-mapping>
Yes, I do want cascade = "all" on the one-to-one side so I changed that. But unfortunately it didn't help. I also tried removing the cascade attribute from the many-to-one side since I don't think it's really needed, but that didn't help either.
What else could be the source of the problem? -The value of "fetch"? Or should I remove some other attribute?
Should one of the sides of the relationship have an "inverse" attribute? I'm not sure about this.. (Basically this relationship is one-to-one on both sides. There will just temporarily be more than one Document connected to a specific Client, before the Client's older Document is removed.)
I'll try to read more about this myself but I would appreciate some more help also.
Yes, there does need to have some sort of inverse to tell Hibernate that those two mappings map the same relationship.
Joined: Feb 12, 2008
Ok, I thought about this some more and I realized that what I really needed was a "typical bidirectional one-to-one relationship". (If I remove the old Document Before I save the new one there's no need for many-to-one.)
Though, "Hibernate in Action" says that one side of this relationship must be mapped as many-to-one with a unique constraint, so I did this new mapping according to the book:
(In Client.hbm.xml): <many-to-one name = "docRef" column = "docRef" unique = "true" class = "BusinessLogic.Entities.Document" cascade = "all" fetch = "join"/>
(In Document.hbm.xml): <one-to-one name = "client" property-ref = "docRef" cascade = "save-update" class = "BusinessLogic.Entities.Client" fetch = "join"/>
I'll describe shortly what I'm trying to do and what causes a problem: First I fetch the right Client object from the db. Then a method checks if that Client had any old Documents saved and if so removes them (it should only be one). - This works. Then a new Document is created and saved to the db, using the reference to that Client. After this I set the docRef property of Client to point to the new Document, which also works.
What doesn't work is this: When I check the db after program execution the Client reference of the newly saved Document is NULL.
I tried to add a call to session.update for the new Document but that didn't help.
I've really thought hard about this and read my book but I'm not getting anywhere, so could you Please help me, Mark or anyone who can?