Reputation: 19150
I’m using JPA 2.0 with Hibernate 4.1.0.Final. I’m having trouble figuring out how to Map a couple of entities. I have a Group and a GroupMember class, but the following mappings …
@Entity
@Table(name = "group")
public class Group
{
@Id
@NotNull
@GeneratedValue(generator = "uuid-strategy")
@Column(name = "ID")
private String id;
…
@ManyToMany
@ElementCollection
@CollectionTable(name="group_member", joinColumns=@JoinColumn(name="GROUP_ID"))
private Set<GroupMember> members;
@Entity
@Table(name = "group_member")
public class GroupMember
{
@Id
@NotNull
@GeneratedValue(generator = "uuid-strategy")
@Column(name = "ID")
private String id;
…
@ManyToOne
@JoinColumn(name = "GROUP_ID", nullable = false, updatable = true)
private Group group;
result in this exception …
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:914)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:889)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:287)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 38 more
Caused by: org.hibernate.MappingException: Foreign key (FK4719AC489E4DD84:group_member [members_ID])) must have same number of columns as the referenced primary key (group_member [GROUP_ID,members_ID])
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:110)
at org.hibernate.mapping.ForeignKey.alignColumns(ForeignKey.java:93)
at org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:1704)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1627)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1362)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1727)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:88)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
How do I map my GroupMembers field into my Group class?
... 44 more
Upvotes: 0
Views: 8360
Reputation: 23226
The issue is that you have a @OneToMany on one side and @ManyToMany on the other. Additionally @ElementCollection and @CollectionTable are the wrong annotations in this case as your are dealing with a collection of Entities rather than Embeddables:
http://en.wikibooks.org/wiki/Java_Persistence/ElementCollection
If the model is such that one Group can have many Members and a Member can belong to many Groups then you have two options. You can use @ManyToMany Group <> Member (and use @JoinTable to define the Join table) or, you can define an intermediate entity for the join and map the relationships as @OneToMany.
The latter is the recommended approach as it will allow you to store extra information about the relationship: for example, in this case you could define an extra field on GroupMember to store the date the Member joined the Group.
@Entity
@Table(name = "group")
public class Group
{
@Id
@NotNull
@GeneratedValue(generator = "uuid-strategy")
@Column(name = "ID")
private String id;
…
@OneToMany(mappedBy = "group")
private Set<GroupMember> members;
}
@Entity
@Table(name = "member")
public class Member
{
@Id
@NotNull
@GeneratedValue(generator = "uuid-strategy")
@Column(name = "ID")
private String id;
…
@OneToMany(mappedBy = "member")
private Set<GroupMember> groups;
}
@Entity
@Table(name = "group_member")
public class GroupMember
{
@Id
@NotNull
@GeneratedValue(generator = "uuid-strategy")
@Column(name = "ID")
private String id;
…
@ManyToOne
@JoinColumn(name = "GROUP_ID", nullable = false, updatable = true)
private Group group;
@ManyToOne
@JoinColumn(name = "MEMBER_ID", nullable = false, updatable = true)
private Member member;
}
Upvotes: 2