Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA Hibernate One-to-One relationship

I have a one-to-one relationship but hibernatetool complains when generating the schema. Here's an example that shows the problem:

@Entity public class Person {     @Id     public int id;      @OneToOne     public OtherInfo otherInfo;      rest of attributes ... } 

Person has a one-to-one relationship with OtherInfo:

@Entity public class OtherInfo {     @Id     @OneToOne(mappedBy="otherInfo")     public Person person;      rest of attributes ... } 

Person is owning side of OtherInfo. OtherInfo is the owned side so person uses mappedBy to specify the attribute name "otherInfo" in Person.

I get the following error when using hibernatetool to generate the database schema:

org.hibernate.MappingException: Could not determine type for: Person, at table: OtherInfo, for columns: [org.hibernate.mapping.Column(person)]         at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:292)         at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:175)         at org.hibernate.cfg.Configuration.iterateGenerators(Configuration.java:743)         at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.java:854)         at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:128)         ... 

Any idea why? Am I a doing something wrong or is this a Hibernate bug?

like image 647
Steve Kuo Avatar asked Apr 24 '09 21:04

Steve Kuo


People also ask

How does JPA define one-to-one relationships?

For a One-to-One relationship in JPA, each entity instance is related to a single instance of another entity. It means each row of one entity is referred to one and only one row of another entity.

How do you make a one-to-one relationship in Hibernate?

Define Hibernate Mapping FileThe <many-to-one> element will be used to define the rule to establish a one-to-one relationship between EMPLOYEE and ADDRESS entities, but column attribute will be set to unique constraint and rest of the mapping file will remain as it was in case of many-to-one association.

How does JPA define one-to-one mapping?

The One-To-One mapping represents a single-valued association where an instance of one entity is associated with an instance of another entity. In this type of association one instance of source entity can be mapped atmost one instance of target entity.

How do I create a one-to-one map in JPA?

Implementing With a Foreign Key in JPA. Note that we place the @OneToOne annotation on the related entity field, Address. Also, we need to place the @JoinColumn annotation to configure the name of the column in the users table that maps to the primary key in the address table.


2 Answers

JPA doesn't allow the @Id annotation on a OneToOne or ManyToOne mapping. What you are trying to do is one-to-one entity association with shared primary key. The simplest case is unidirectional one-to-one with shared key:

@Entity public class Person {     @Id     private int id;      @OneToOne     @PrimaryKeyJoinColumn     private OtherInfo otherInfo;      rest of attributes ... } 

The main problem with this is that JPA provides no support for shared primary key generation in OtherInfo entity. The classic book Java Persistence with Hibernate by Bauer and King gives the following solution to the problem using Hibernate extension:

@Entity public class OtherInfo {     @Id @GeneratedValue(generator = "customForeignGenerator")     @org.hibernate.annotations.GenericGenerator(         name = "customForeignGenerator",         strategy = "foreign",         parameters = @Parameter(name = "property", value = "person")     )     private Long id;      @OneToOne(mappedBy="otherInfo")     @PrimaryKeyJoinColumn     public Person person;      rest of attributes ... } 

Also, see here.

like image 141
topchef Avatar answered Sep 20 '22 03:09

topchef


This should be working too using JPA 2.0 @MapsId annotation instead of Hibernate's GenericGenerator:

@Entity public class Person {      @Id     @GeneratedValue     public int id;      @OneToOne     @PrimaryKeyJoinColumn     public OtherInfo otherInfo;      rest of attributes ... }  @Entity public class OtherInfo {      @Id     public int id;      @MapsId     @OneToOne     @JoinColumn(name="id")     public Person person;      rest of attributes ... } 

More details on this in Hibernate 4.1 documentation under section 5.1.2.2.7.

like image 33
Mariusz Avatar answered Sep 19 '22 03:09

Mariusz