views:

8469

answers:

5

Can somebody please give me an example of a unidirectional @OneToOne primary-key mapping in Hibernate ? I've tried numerous combinations, and so far the best thing I've gotten is this :

@Entity
@Table(name = "paper_cheque_stop_metadata")
@org.hibernate.annotations.Entity(mutable = false)
public class PaperChequeStopMetadata implements Serializable, SecurityEventAware {

private static final long serialVersionUID = 1L;

@Id
@JoinColumn(name = "paper_cheque_id")
@OneToOne(cascade = {}, fetch = FetchType.EAGER, optional = false, targetEntity = PaperCheque.class)
private PaperCheque paperCheque;
}

Whenever Hibernate tries to automatically generate the schema for the above mapping, it tries to create the primary key as a blob, instead of as a long, which is the id type of PaperCheque. Can somebody please help me ? If I can't get an exact solution, something close would do, but I'd appreciate any response.

+1  A: 

I saved this discussion when I implemented a couple of @OneToOne mappings, I hope it can be of use to you too, but we don't let Hibernate create the database for us.

Note the GenericGenerator annotation.

Anyway, I have this code working:

@Entity
@Table(name = "message")
public class Message implements java.io.Serializable
{
    // ...

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "message_id")
public MessageContent getMessageContent()
{
 return messageContent;
}

    // ...
 }

@Entity
@Table(name = "message_content")
@GenericGenerator(name = "MessageContent", strategy = "foreign", parameters = { @org.hibernate.annotations.Parameter(name = "property", value = "message") })
public class MessageContent implements java.io.Serializable
{
    // ...

@Id
@Column(name = "message_id", unique = true, nullable = false)
// See http://forum.hibernate.org/viewtopic.php?p=2381079
@GeneratedValue(generator = "MessageContent")
public Integer getMessageId()
{
 return this.messageId;
}

    // ...
 }
divideandconquer.se
+1  A: 

Your intention is to have a 1-1 relationship between PaperChequeStopMetaData and PaperCheque? If that's so, you can't define the PaperCheque instance as the @Id of PaperChequeStopMetaData, you have to define a separate @Id column in PaperChequeStopMetaData.

David M. Karr
A: 

Hey guys,

Thank you both for your answers. I kept experimenting, and here's what I got working :

@Entity
@Table(name = "paper_cheque_stop_metadata")
@org.hibernate.annotations.Entity(mutable = false)
public class PaperChequeStopMetadata implements Serializable, SecurityEventAware {

private static final long serialVersionUID = 1L;

@SuppressWarnings("unused")
@Id
@Column(name = "paper_cheque_id")
@AccessType("property")
private long id;

@OneToOne(cascade = {}, fetch = FetchType.EAGER, optional = false, targetEntity = PaperCheque.class)
@PrimaryKeyJoinColumn(name = "paper_cheque_id")
@JoinColumn(name = "paper_cheque_id", insertable = true)
@NotNull
private PaperCheque paperCheque;

@XmlAttribute(namespace = XMLNS, name = "paper-cheque-id", required = true)
public final long getId() {
 return this.paperCheque.getId();
}

public final void setId(long id) {
 //this.id = id;
 //NOOP, this is essentially a pseudo-property
}
}

This is, by all means, a disgusting hack, but it gets me everything I wanted. The paperCheque property accessors are as normal (not shown). I've run into this kind of unidirectional OneToOne mapping problem before and settled for much worse solutions, but this time I decided I was going to figure out out, so I kept hacking away at it. Once again, thank you both for your answers, it's much appreciated.

Alex Marshall
+2  A: 

You should stay away from hibernate's OneToOne mapping, it is very dangerous. see http://opensource.atlassian.com/projects/hibernate/browse/HHH-2128

you are better off using ManyToOne mappings.

Pat
Thank you for pointing that out, Pat. Fortunately, all of my OneToOne mappings are non-null relationships and so are not affected by the issue.
Alex Marshall
I hope you have added in LARGE screaming letters multiple comments that no one should ever think about making the relationship optional. One accidental release to production for 30 seconds and you have data corruption.For me, the risk was too large - even if it would not happen for 3 years. I liken it to having high-explosives in your house. You are safe and careful 99.999% of the time. But one slip-up and boom. Why have the high-explosives at all?
Pat
A: 

Plz provide its db script.

Arv