Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping ManyToMany with composite Primary key and Annotation:

Tags:

I'm trying to create manytomany realation between Student and Teaching Course using Composite Primary key:

my classes:

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

Collection Objects:

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

    }

Now The primary Key:

@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() {}


}

When I'm trying to Persist Student I got the following error:

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

What am I doing wrong?

like image 654
danny.lesnik Avatar asked Jun 19 '11 23:06

danny.lesnik


People also ask

How do you map a composite primary key?

A composite primary key is mapped using an Embeddable type in hibernate. We'll first create an Embeddable type called EmployeeIdentity containing the employeeId and companyId fields, and then create the Employee entity which will embed the EmployeeIdentity type.

What annotation is used for a composite primary key type?

The EmbeddedId and IdClass annotations are used to denote composite primary keys.

How do I use ManyToMany annotations?

In order to map a many-to-many association, we use the @ManyToMany, @JoinTable and @JoinColumn annotations. Let's have a closer look at them. The @ManyToMany annotation is used in both classes to create the many-to-many relationship between the entities.


2 Answers

I solved this issue. I mapped Getter instead of field.

public class StudentTClass {

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

    @EmbeddedId
    public StudentTClassPK getPk() {
        return pk;
    }
like image 56
danny.lesnik Avatar answered Sep 24 '22 13:09

danny.lesnik


If you can, I'd seriously suggest removing the composite keys. Worth with simple primary keys can both make a lot of problems go away and simplify your code. I have used composite keys in a database in the past because I had no ability to modify the db. Unfortunately I don't have the code. But I do remember it took some work to get it all working correctly. Sorry, can't help more.

like image 30
drekka Avatar answered Sep 23 '22 13:09

drekka