JPA映射:外键在引用的主键中必须具有相同数量的列

时间:2014-06-06 13:29:51

标签: hibernate jpa mapping jpa-2.0

我正在使用JPA 2.0和Hibernate 4.1.0.Final。我无法弄清楚如何映射几个实体。我有一个Group和一个GroupMember类,但是以下映射......

@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;

导致此例外...

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)

如何将GroupMembers字段映射到我的Group类?

    ... 44 more

1 个答案:

答案 0 :(得分:2)

问题是你的一方是@OneToMany而另一方是@ManyToMany。另外@ElementCollection和@CollectionTable在这种情况下是错误的注释,因为你正在处理一组实体而不是Embeddables:

http://en.wikibooks.org/wiki/Java_Persistence/ElementCollection

如果模型是这样的,一个组可以有许多成员,而一个成员可以属于多个组,那么您有两个选择。您可以使用@ManyToMany Group&lt;&gt;成员(并使用@JoinTable定义Join表),或者,您可以为连接定义中间实体,并将关系映射为@OneToMany。

后者是推荐的方法,因为它允许您存储有关关系的额外信息:例如,在这种情况下,您可以在GroupMember上定义一个额外字段,以存储成员加入该组的日期。

@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;
}