Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-Column Join in Hibernate/JPA Annotations

I have two entities which I would like to join through multiple columns. These columns are shared by an @Embeddable object that is shared by both entities. In the example below, Foo can have only one Bar but Bar can have multiple Foos (where AnEmbeddableObject is a unique key for Bar). Here is an example:

@Entity @Table(name = "foo") public class Foo {     @Id     @Column(name = "id")     @GeneratedValue(generator = "seqGen")     @SequenceGenerator(name = "seqGen", sequenceName = "FOO_ID_SEQ", allocationSize = 1)     private Long id;     @Embedded     private AnEmbeddableObject anEmbeddableObject;     @ManyToOne(targetEntity = Bar.class, fetch = FetchType.LAZY)     @JoinColumns( {         @JoinColumn(name = "column_1", referencedColumnName = "column_1"),         @JoinColumn(name = "column_2", referencedColumnName = "column_2"),         @JoinColumn(name = "column_3", referencedColumnName = "column_3"),         @JoinColumn(name = "column_4", referencedColumnName = "column_4")     })     private Bar bar;      // ... rest of class } 

And the Bar class:

@Entity @Table(name = "bar") public class Bar {     @Id     @Column(name = "id")     @GeneratedValue(generator = "seqGen")     @SequenceGenerator(name = "seqGen", sequenceName = "BAR_ID_SEQ", allocationSize = 1)     private Long id;     @Embedded     private AnEmbeddableObject anEmbeddableObject;      // ... rest of class } 

Finally the AnEmbeddedObject class:

@Embeddable public class AnEmbeddedObject {     @Column(name = "column_1")     private Long column1;     @Column(name = "column_2")     private Long column2;     @Column(name = "column_3")     private Long column3;     @Column(name = "column_4")     private Long column4;      // ... rest of class } 

Obviously the schema is poorly normalised, it is a restriction that AnEmbeddedObject's fields are repeated in each table.

The problem I have is that I receive this error when I try to start up Hibernate:

org.hibernate.AnnotationException: referencedColumnNames(column_1, column_2, column_3, column_4) of Foo.bar referencing Bar not mapped to a single property 

I have tried marking the JoinColumns are not insertable and updatable, but with no luck. Is there a way to express this with Hibernate/JPA annotations?

like image 787
bowsie Avatar asked Jun 01 '12 07:06

bowsie


People also ask

What is the use of @JoinColumn annotation?

Annotation Type JoinColumn. Specifies a column for joining an entity association or element collection. If the JoinColumn annotation itself is defaulted, a single join column is assumed and the default values apply. (Optional) The SQL fragment that is used when generating the DDL for the column.

What is the use of @column annotation?

@Column annotation is used for Adding the column the name in the table of a particular MySQL database.

What is the use of @JoinTable annotation?

Annotation Type JoinTable. Specifies the mapping of associations. It is applied to the owning side of an association. A join table is typically used in the mapping of many-to-many and unidirectional one-to-many associations.

What is referencedColumnName in @JoinColumn Hibernate?

The usage of the isbn as the foreign key requires an additional @JoinColumn annotation. The referencedColumnName attribute tells Hibernate the name of the database column it shall use as the foreign key.


1 Answers

This worked for me . In my case 2 tables foo and boo have to be joined based on 3 different columns.Please note in my case ,in boo the 3 common columns are not primary key

i.e., one to one mapping based on 3 different columns

@Entity @Table(name = "foo") public class foo implements Serializable {     @Column(name="foocol1")     private String foocol1;     //add getter setter     @Column(name="foocol2")     private String foocol2;     //add getter setter     @Column(name="foocol3")     private String foocol3;     //add getter setter     private Boo boo;     private int id;     @Id     @GeneratedValue(strategy = GenerationType.IDENTITY)     @Column(name = "brsitem_id", updatable = false)     public int getId()     {         return this.id;     }     public void setId(int id)     {         this.id = id;     }     @OneToOne     @JoinColumns(     {         @JoinColumn(updatable=false,insertable=false, name="foocol1", referencedColumnName="boocol1"),         @JoinColumn(updatable=false,insertable=false, name="foocol2", referencedColumnName="boocol2"),         @JoinColumn(updatable=false,insertable=false, name="foocol3", referencedColumnName="boocol3")     }     )     public Boo getBoo()     {         return boo;     }     public void setBoo(Boo boo)     {         this.boo = boo;     } }      @Entity @Table(name = "boo") public class Boo implements Serializable {     private int id;     @Column(name="boocol1")     private String boocol1;     //add getter setter     @Column(name="boocol2")     private String boocol2;     //add getter setter     @Column(name="boocol3")     private String boocol3;     //add getter setter     @Id     @GeneratedValue(strategy = GenerationType.IDENTITY)     @Column(name = "item_id", updatable = false)     public int getId()     {         return id;     }     public void setId(int id)     {         this.id = id;     } } 
like image 158
Mohammed Rafeeq Avatar answered Sep 21 '22 06:09

Mohammed Rafeeq