-->
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.  [ 2 posts ] 
Author Message
 Post subject: Trying to understand one-to-one mapping
PostPosted: Sat May 15, 2004 2:06 am 
Newbie

Joined: Fri May 07, 2004 2:18 am
Posts: 19
Hello

I am finally getting the hang of hibernate but I cant seem to resolve this simple problem
I am using Xdoclet-1.2.1 Hibernate-2.1.3

I have 2 classes One and Two. I would like a undirectional one-to-one relationship between them. ie I can have a One but no Two but never a Two without a One.

Here are the classes

/**
* @author Marcus
* @hibernate.class table="one"
*
*/
public class One {
private long nid = -1;
private Two two;
/**
*@hibernate.id unsaved-value="-1" generator-class="native"
*/
public long getNid() {
return nid;
}

public void setNid(long nid) {
this.nid = nid;
}

/**
* @hibernate.one-to-one name="ttoo" cascade="all"
*/
public Two getTwo() {
return two;
}
public void setTwo(Two two) {
this.two = two;
}
public void addTwo(Two two) {
two.setOne(this);
this.two = two;
}

/**
* @hibernate.class table="two"
*/
public class Two {
private long nid;
One one;
public Two(){
}

public Two(One one){
this.one = one;
}
/**
*@hibernate.id name="nid" generator-class="foreign"
*@hibernate.generator-param name="property" value="one"
*/
public long getNid() {
return nid;
}

public void setNid(long nid) {
this.nid = nid;
}

/**
*@hibernate.one-to-one name="one" constrained="true"
* @return Value of property party.
*/
public One getOne() {
return one;
}

public void setOne(One one) {
this.one = one;
}
}

And here is the code I am trying to use

One one = new One();
Two two = new Two();
one.addTwo(two);
session.save(one);
session.flush();

One gets saved but two doesnt.
Also here are a few things I have figured out about Xdoclet
1)The name attribute is not supported for one-to-one so no matter what you put it changes it
2)attribute parent-ref is not supported by xdoclet and gives an error

Xdoclet does properly generate the .hbm files and I have no problem uploading the schema to database

Here are the mappings

<class
name="org.marcus.One"
table="one"
dynamic-update="false"
dynamic-insert="false"
>
<id
name="nid"
column="nid"
type="long"
unsaved-value="-1"
>
<generator class="native">
</generator>
</id>

<one-to-one
name="two"
class="org.marcus.Two"
cascade="all"
outer-join="auto"
constrained="false"
/>
</class>

<class
name="org.marcus.Two"
table="two"
dynamic-update="false"
dynamic-insert="false"
>
<id
name="nid"
column="nid"
type="long"
>
<generator class="foreign">
<param name="property">one</param>
</generator>
</id>

<one-to-one
name="one"
class="org.marcus.One"
cascade="none"
outer-join="auto"
constrained="true"
/>
</class>

Now I think I understand the concept behind the one-to-one mappping but obviously I am missing something

Any help would be appreciated


Top
 Profile  
 
 Post subject: I found the answer
PostPosted: Sat May 15, 2004 3:37 pm 
Newbie

Joined: Fri May 07, 2004 2:18 am
Posts: 19
I figured out what I had done wrong. Basically since the primary keys are primitive types I need to explicitly define an unsaved value for both objects.
In this case here is the correct code

/**
* @author Marcus
* @hibernate.class table="one"
*
*/
public class One implements Serializable {
private long nid = -1;

private String www = "";

private Two two;
/**
*@hibernate.id unsaved-value="-1" generator-class="sequence"
*
*/
public long getNid() {
return nid;
}

public void setNid(long nid) {
this.nid = nid;
}

/**
* @hibernate.one-to-one cascade="all"
* @return Value of property userlogin.
*/
public Two getTwo() {
return two;
}

public void setTwo(Two two) {
this.two = two;
}

public void addTwo(Two twwo) {
twwo.setOne(this);
setTwo(twwo);
}
/**
* @hibernate.property
*
*/
public String getWww() {
return www;
}

public void setWww(String www) {
this.www = www;
}

}

/**
* @author Marcus
* @hibernate.class table="two"
*
*/
public class Two implements Serializable{
private long nid = -1;
private One one;
public Two(){
}

public Two(One one){
this.one = one;
}
/**
*@hibernate.id unsaved-value="-1" generator-class="foreign"
*@hibernate.generator-param name="property" value="one"
*
* @return Value of property userlogin.
*/
public long getNid() {
return nid;
}

public void setNid(long nid) {
this.nid = nid;
}

/**
*@hibernate.one-to-one constrained="true"
*
*/
public One getOne() {
return one;
}

public void setOne(One one) {
this.one = one;
}
}

Now the following code works correctly

One one = new One();
Two two = new Two();
one.addTwo(two);
session.save(one);
session.flush();

I hopes this helps others trying to figure this out. It is so simple and a complete example like the one above would have saved so much time.

I do have a few questions about deleting objects.
I had assumed that by doing adding this function to the Class One

public void deleteTwo(){
two=null;
}
and then calling this code in a later session. Assume I have retrieved a previously saved instance of One

one.deleteTwo();
session.save(one);
session.flush();
would delete two.
Obviously I was wrong. I know I can explicitly call session.delete(two). But what happens in the case where an instance of One is retrieved in one session and then passed to a different jvm through rmi where it is altered by calling one.deleteTwo() and then sent back to save its new state. Would I specifically have to do this
if(one.getTwo == null){
session.delete(??);
}

I put the question marks in above because I dont know what to delete. Obviously I cant delete something that is null. Would I have to retrieve a specific instance from the database and then call delete?

I went ahead and tried this code

Session session = HibernateUtil.currentSession();
Transaction tx= session.beginTransaction();
One one = new One();
one.setWww("wooga");
Two two = new Two();
one.addTwo(two);
System.out.println("www is " + two.getOne().getWww());
one.getTwo();
session.save(one);
session.flush();
tx.commit();
HibernateUtil.closeSession();

session = HibernateUtil.currentSession();
tx= session.beginTransaction();
one = (One) session.load(One.class, new Long(1));
System.out.println("www is " + two.getOne().getWww());
one.deleteTwo();
session.save(one);
session.flush();
tx.commit();
HibernateUtil.closeSession();

As I expected two still exists in the database;

What I would like to know is if there is a natural java way to make two not exist anymore.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.