使用复合主键和注解映射ManyToMany:

我正在尝试使用复合主键在学生和教学课程之间创造出许多有用的联系:

我的课程:

@Entity @Table(name="Student_mtm_cId") public class Student { private String id; private Set<StudentTClass> teachingClasses = new HashSet<StudentTClass>(); @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.student") public Set<StudentTClass> getTeachingClasses() { return teachingClasses; } public void setTeachingClasses(Set<StudentTClass> teachingClasses) { this.teachingClasses = teachingClasses; } public void addStudentToClass(TeachingClass teachingClass){ StudentTClass studentTClass = new StudentTClass(); studentTClass.setStudent(this); studentTClass.setTeachingClass(teachingClass); teachingClasses.add(studentTClass); } public void setLastName(String lastName) { this.lastName = lastName; } @Id @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid", strategy = "uuid") @Column(name = "student_id", nullable = false) public String getId() { return id; } public void setId(String id) { this.id = id; } //all other setters and getters and isequal/hashCode omitted. } 

TeachingClass:

 @Entity @Table(name="TechingClass_MTM") public class TeachingClass { private String id; private String name; private String description; private Set<StudentTClass> teachingClasses = new HashSet<StudentTClass>(); public TeachingClass(){} public TeachingClass(String name, String description) { super(); this.name = name; this.description = description; } public void addStudentToClass(Student student){ StudentTClass studentTClass = new StudentTClass(); studentTClass.setStudent(student); studentTClass.setTeachingClass(this); teachingClasses.add(studentTClass); } @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.teachingClass") public Set<StudentTClass> getTeachingClasses() { return teachingClasses; } public void setTeachingClasses(Set<StudentTClass> teachingClasses) { this.teachingClasses = teachingClasses; } public void setDescription(String description) { this.description = description; } @Id @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid", strategy = "uuid") @Column(name = "teachingClass_id", nullable = false) public String getId() { return id; } public void setId(String id) { this.id = id; } } 

集合对象:

 @Entity @Table(name = "student_TClass_MTM") @AssociationOverrides({ @AssociationOverride(name = "pk.student", joinColumns = @JoinColumn(name = "student_id")), @AssociationOverride(name = "pk.teachingClass", joinColumns = @JoinColumn(name = "teachingClass_id")) }) public class StudentTClass { @EmbeddedId private StudentTClassPK pk = new StudentTClassPK(); public StudentTClassPK getPk() { return pk; } public void setPk(StudentTClassPK pk) { this.pk = pk; } public StudentTClass() {} @Transient public Student getStudent(){ return this.pk.getStudent(); } @Transient public TeachingClass getTeachingClass(){ return this.pk.getTeachingClass(); } public void setStudent(Student student){ this.pk.setStudent(student); } public void setTeachingClass(TeachingClass teachingClass){ this.pk.setTeachingClass(teachingClass); } } 

现在主要关键:

 @Embeddable public class StudentTClassPK implements Serializable{ private static final long serialVersionUID = -7261887879839337877L; private Student student; private TeachingClass teachingClass; @ManyToOne public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } @ManyToOne public TeachingClass getTeachingClass() { return teachingClass; } public void setTeachingClass(TeachingClass teachingClass) { this.teachingClass = teachingClass; } public StudentTClassPK(Student student, TeachingClass teachingClass) { this.student = student; this.teachingClass = teachingClass; } public StudentTClassPK() {} } 

当我试图坚持学生时,我得到了以下错误:

 Caused by: org.hibernate.MappingException: Could not determine type for: com.vanilla.objects.Student, at table: student_TClass_MTM, for columns: [org.hibernate.mapping.Column(student)] at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:306) at org.hibernate.tuple.PropertyFactory.buildStandardProperty(PropertyFactory.java:143) at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:68) at org.hibernate.mapping.Component.buildType(Component.java:184) at org.hibernate.mapping.Component.getType(Component.java:177) at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:290) at org.hibernate.mapping.RootClass.validate(RootClass.java:236) at org.hibernate.cfg.Configuration.validate(Configuration.java:1362) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1865) at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:855) at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:774) at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417) ... 51 more 

我究竟做错了什么?

我解决了这个问题。 我映射Getter而不是字段。

 public class StudentTClass { //@EmbeddedId private StudentTClassPK pk = new StudentTClassPK(); @EmbeddedId public StudentTClassPK getPk() { return pk; } 

如果可以的话,我会认真的build议删除复合键。 值得使用简单的主键可以使很多问题消失并简化您的代码。 过去我在数据库中使用了复合键,因为我没有能力修改数据库。 不幸的是我没有代码。 但是我确实记得为了使这一切正常工作需要一些工作。 对不起,忍不住了。