2011-06-19 82 views
15

我試圖使用複合主鍵建立學生與教學課程之間多對多realation:映射多對多複合主鍵與註釋:

我的課:

@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 

我在做什麼錯?

回答

13

我解決了這個問題。我將Getter而不是字段映射。

public class StudentTClass { 

    //@EmbeddedId 
    private StudentTClassPK pk = new StudentTClassPK(); 

    @EmbeddedId 
    public StudentTClassPK getPk() { 
     return pk; 
    } 
+0

這工作!我必須在EmbeddedId標記的類中以及標記爲Embedabble的類中執行此操作。 –

5

如果可以,我會認真地建議刪除組合鍵。值得使用簡單的主鍵可以解決很多問題並簡化代碼。過去我在數據庫中使用了複合鍵,因爲我沒有能力修改數據庫。不幸的是我沒有代碼。但是我確實記得它需要一些工作才能正常工作。對不起,忍不住了。

+2

我已經解決了這個問題,我的代碼現在完美的工作。儘管讓Hibernate和Composite主鍵一起工作很棘手,但我認爲它在特殊情況下非常有用,我們需要確保在多對多關係中每個組合只有一行。 –

+2

我同意,有些情況下組合鍵合法有用。 – aroth

+2

@ danny.lesnik組合唯一性可以通過UNIQUE索引來保證。 JPA 2.1提供了與實現無關的語法。 –