Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA: how to use @ElementCollection annotation?

I need your help to map the relation in Hibernate of two tables using the @ElementCollection annotation.

The first one is the parent table
Table name: Parent
DB Columns

KEY1         Char      (first primary key field)
KEY2         Char      (second primary key field)
DESCRIPTION  Char
DEPENDENTID  BigInt

The second one is the dependent table
TableName: Dependent
DB Columns

PARENTID     BigInt    (first primary key field)
CODE         Char      (second primary key field)
FIELD1       Char
FIELD2       Char

I need to define the PK for both tables using @EmbeddedId annotation, so I have created the two classes:

@Embeddable
public class ParentPK implements Serializable
{
   @Column(name="K1")
   private String iK1;
   @Column(name="K2")
   private String iK2;
  // I omit the constructor, getter, setter, equals, hashcode method 
}

@Embeddable
public class DependentPK implements Serializable
{
  @Column(name="PARENTID")
  private String iParentId;
  @Column(name="CODE")
  private String iCode;
  // I omit the constructor, getter, setter, equals, hashcode method 
}

and then I've created the two beans:
The class for the DEPENDENT table.
Note that in this class I do not want to have any relational annotation

@Entity
@Table(name = "DEPENDENT")
public class DependentBean implements Serializable
{
   @EmbeddedId
   private DependentPK iDependentPK;
   @Column(name = "FIELD1")
   private String iField1;
   @Column(name = "FIELD2")
   private String iField2;
   // I omit the constructor, getter, setter methods
}

And the class for the PARENT table

@Entity
@Table(name = "PARENT")
public class ParentBean implements Serializable
{
   @EmbeddedId
   ParentPK iParentPK;
   @Column(name = "DESCRIPTION")
   private String iDescription;
   @Column(name = "DEPENDENTID")
   private long iDependentId;
   @ElementCollection
   @CollectionTable(name="DEPENDENT", joinColumns={@JoinColumn(name="PARENTID",  referencedColumnName="DEPENDENTID")})
   private Set<DependentBean> iDependentBeans = new HashSet<DependentBean>();
   // I omit the constructor, getter, setter methods
}

When I try to deploy I got the error:

Caused by: org.hibernate.MappingException: Foreign key (FK9619C2A17B05CB2:DEPENDENT [iDependentBeans_PARENTID,iDependentBeans_CODE])) must have same number of columns as the referenced primary key (DEPENDENT [PARENTID,iDependentBeans_PARENTID,iDependentBeans_CODE])

So I'm doing something wrong, but I can not imagine what. Could anyone wants to help me, please?

like image 383
gpezzini Avatar asked Aug 23 '13 15:08

gpezzini


People also ask

What is @ElementCollection in JPA?

JPA 2.0 defines an ElementCollection mapping. It is meant to handle several non-standard relationship mappings. An ElementCollection can be used to define a one-to-many relationship to an Embeddable object, or a Basic value (such as a collection of String s).

What is @ElementCollection in spring boot?

The @ElementCollection is used to map non-entities (embeddable or basic) while @OneToMany is used to map entities. We need to use @Embeddable annotation to make an embeddable class(generally @Embeddable used with User defined class). When we say basic types that means String or any other wrapper classes.

What is @ElementCollection in java?

Annotation Type ElementCollection. @Target(value={METHOD,FIELD}) @Retention(value=RUNTIME) public @interface ElementCollection. Defines a collection of instances of a basic type or embeddable class. Must be specified if the collection is to be mapped by means of a collection table.

What is the difference between @ElementCollection and @OneToMany?

I believe @ElementCollection is mainly for mapping non-entities (embeddable or basic) while @OneToMany is used to map entities. So which one to use depend on what you want to achieve.


1 Answers

@ElementCollection should be used with basic type or embeddable class, not for entity.

The DependentBean is an Entity.

Try to use One To Many Mapping and modify your schema

PARENT schema

KEY1         Char      (PK)
KEY2         Char      (PK)
DEPENDENTID  BigInt    (PK)
DESCRIPTION  Char

DEPENDENT schema

CODE         Char      (PK)
PARENTID     BigInt    (FK)
KEY1         Char      (FK)
KEY2         Char      (FK)
FIELD1       Char
FIELD2       Char

One To Many mapping

ParentPK

@Embeddable
public class ParentPK {
    @Column(name = "K1")
    private String iK1;
    @Column(name = "K2")
    private String iK2;
    @Column(name = "DEPENDENTID")
    private long iDependentId;
}

ParentBean

@Entity
@Table(name = "PARENT")
public class ParentBean {
    @EmbeddedId
    ParentPK iParentPK;

    @OneToMany(mappedBy = "parent")
    List<DependentBean> iDependentBeans;
}

DependentBean

@Entity
@Table(name = "DEPENDENT")
public class DependentBean {
    @Id
    @Column(name = "CODE")
    private String iCode;

    @ManyToOne
    @JoinColumns({ 
      @JoinColumn(name = "PARENTID", referencedColumnName = "iDependentId"),  
      @JoinColumn(name = "K1", referencedColumnName = "iK1"),
      @JoinColumn(name = "K2", referencedColumnName = "iK2") })
    ParentBean parent;
}
like image 188
study Avatar answered Oct 01 '22 02:10

study