-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Bidirectional one-to-one. One side not saved to database.
PostPosted: Tue Sep 09, 2008 7:13 am 
Newbie

Joined: Fri Jun 13, 2008 4:52 pm
Posts: 9
Location: Västerås, Sweden
Hello, Hibernate users,

I'm using the following...

Hibernate version: 3.2.6
Database: MySQL Server 5.0.51a

..and I'm having a problem with a bidirectional one-to-one relationship. It exists between my entities "Client" and "Document".

I've written the mapping of the relationship according to "Hibernate in Action" and these are the important lines:

(In Client.hbm.xml):
Code:
<many-to-one name = "docRef" column = "docRef" unique = "true" class = "BusinessLogic.Entities.Document" cascade = "all" fetch = "join"/>


(In Document.hbm.xml):
Code:
<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.

Does anyone have an idea why this is happening?

I can post more information about the tables in the db later if needed.

I just really need some help 'cause I've tried lots of ways to solve the problem myself but I'm not getting anywhere.

Thanks in advance!

/Ylva


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 09, 2008 7:55 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
You've defined a foreign key relationship from Client to Document. At the schema level it means the Client table has the ID of the Document as a foreign key but there's no Client ID column in the Document table. If you use hibernate to generate the schema from your mapping files you'll see this. That's why the client ref is null in your pre-existing schema.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 09, 2008 11:03 am 
Newbie

Joined: Fri Jun 13, 2008 4:52 pm
Posts: 9
Location: Västerås, Sweden
Thanks for your reply, Mike!

Yes, there is actually a Client ID column in the Document table. The database schema existed before I started doing this application. In fact I created it by hand and I used it in the first version of this application which used JPA and not Hibernate. Everything worked then so there must be a way to make it work with Hibernate.

These are the relevant parts of the database schema:
Code:
---------------------Document--------------------------------
| document    | CREATE TABLE `document` (
  `docId` bigint(20) unsigned NOT NULL auto_increment,
  `clientId` bigint(20) unsigned default NULL,
  .....
  PRIMARY KEY  (`docId`),
  UNIQUE KEY `docId` (`docId`),
  KEY `clientId` (`clientId`),
  CONSTRAINT `doc_ibfk_1` FOREIGN KEY (`clientId`) REFERENCES `client` (`clientId`),
  CONSTRAINT `FK_doc_clientId` FOREIGN KEY (`clientId`) REFERENCES `client` (`clientId`)
) ENGINE=InnoDB AUTO_INCREMENT=60 ... |

----------------------Client-------------------------------------
| client | CREATE TABLE `client` (
  `clientId` bigint(20) unsigned NOT NULL auto_increment,
  .......
  `docRef` bigint(20) unsigned default NULL,
  PRIMARY KEY  (`clientId`),
  UNIQUE KEY `clientId` (`clientId`),
  KEY `docRef` (`docRef`),
  CONSTRAINT `FK_client_docRef` FOREIGN KEY (`docRef`) REFERENCES `document` (`docId`),
  CONSTRAINT `client_ibfk_1` FOREIGN KEY (`docRef`) REFERENCES `document` (`docId`)
) ENGINE=InnoDB AUTO_INCREMENT=19 ... |


(Some of the things including the extra FK Constraints must have been added by JPA since I didn't write them from the start.)

But just now I realized that I wanted the 'clientId' of Document to be NOT NULL so I changed that in the db schema (in case it would help solving my problem).
The new line (in the Document table) looks like this:
Code:
`clientId` bigint(20) unsigned NOT NULL,


But that was obviously a bad idea because when I tried running the app. I got the SQLException "Field 'clientId' doesn't have a default value".
Is it not possible to set a Foreign Key field to 'NOT NULL'? (I'm running out of time. That's why I'm testing things without being sure about them.)

Anyway, the problem was there even before that little change and I still have no idea what to do about it. Please help me figure it out!

/Ylva


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 09, 2008 11:42 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
If you can you should drop the clientId column from document - you don't need it for the java to work. Without the clientId column you can still load a document object and navigate to the client in java (and vice versa).

If you need the clientId for some external reason you could use the many-to-one with unique=true in BOTH directions. However, if you do this you'll have to explicitly set the client in the document as well as the document in the client.

Obviously this won't work if the foreign key columns are not-null and the primary keys auto assigned. Hibernate will have to update the foreign keys of both doc and client _after_ the objects have been created and hence their IDs assigned.


(In Client.hbm.xml):
Code:
<many-to-one name = "docRef" column = "docRef" unique = "true" class = "BusinessLogic.Entities.Document" cascade = "all" fetch = "join"/>


(In Document.hbm.xml):
Code:
<many-to-one name = "client" column="clientId" class = "BusinessLogic.Entities.Client" cascade = "all" fetch = "join"/>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 09, 2008 12:41 pm 
Newbie

Joined: Fri Jun 13, 2008 4:52 pm
Posts: 9
Location: Västerås, Sweden
THANK YOU, Mike!!

That 'many-to-one with unique constraint on both sides' did it! (When I'd changed back the 'NOT NULL' to 'default NULL' for clientId of course.)

I wanted to keep the clientId column since I'm using the same database with my other application and I didn't want to risk ruining that.

Now the whole application works, thanks to you! :-)
As you can see I've rated your latest answer 'helpful', which it was indeed. (I can see why you have so many credits..)

All the best to you!

/Ylva


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.