19

I need a many to many hibernate mapping needed 3 joins. I've tried to find out a solution without intermediate entity like LecturerCourse.

I have a many to many relation in my database between my lecturer and course tables. A course can be given by several lecturer while a lecturer can give several courses.

I have courses stored before hand. However, I need to assign courses to lecturer. When I assign courses I also store the capacity of that course.

My database diagram:

enter image description here

I use hibernate and spring. I need a hibernate mapping when a course is assign any lecturer. I need to add values to capacity field.

My lecturer mapping :

@Entity
@Table(name="LECTURER")
public class Lecturer {

    @Id 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="LECTURER_ID_SEQ")
    @SequenceGenerator(name="LECTURER_ID_SEQ", sequenceName="LECTURER_ID_SEQ")
    private Long Id;

    @Column(name="NAME")
    private String name;

    @Column(name="SURNAME")
    private String surname;


    @Column(name="EMAIL")
    private String email;

    @Column(name="USERNAME")
    private String username;

    @Column(name="PASSWORD")
    private String Password;

    @ManyToMany
    @JoinTable(
          name="LECTURER_COURSE",
          joinColumns=@JoinColumn(name="LECTURER_ID"),
          inverseJoinColumns=@JoinColumn(name="COURSE_ID")
      )
    private List<Course> courses;

    //getters - setters
}

My course mapping :

@Entity
@Table(name="COURSE")
public class Course {

    @Id 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="COURSE_ID_SEQ")
    @SequenceGenerator(name="COURSE_ID_SEQ", sequenceName="COURSE_ID_SEQ")
    private Long id;

    @Column(name="NAME")
    private String name;

    @Column(name="CODE")
    private String code;
}

Any idea how to solve my problem ?

John Giotta
  • 16,432
  • 7
  • 52
  • 82
erencan
  • 3,725
  • 5
  • 32
  • 50
  • What have you tried? If you add a course to a lecturer, and then save the lecturer, can you see in the database if the LECTURER and LECTURER_COURSE tables are populated? – John Farrelly Apr 24 '12 at 10:53
  • yes it will populate the database. my question is how to store capacity values for courses. a course may have several capacities for each lecturer. how can i map the capacity field? – erencan Apr 24 '12 at 11:07
  • Have a look at axtavt's answer to this question: http://stackoverflow.com/questions/4751902/adding-additional-property-to-hibernate-jointable – John Farrelly Apr 24 '12 at 11:21
  • @erencan Hi I have the same problem, did you try solution in the like John mention? – macemers Jan 13 '15 at 07:12

1 Answers1

27

You need to use @EmbeddedId and @Embeddable annotations to solve this issue:

Lecturer Class:

@Entity
@Table(name="LECTURER")
public class Lecturer {

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.lecturer", cascade=CascadeType.ALL)
Set<LecturerCourse> lecturerCourses == new HashSet<LecturerCourse>();

//all others properties Setters and getters are less relevant.

}

Course class:

@Entity
@Table(name="COURSE")
public class Course {

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.course", cascade=CascadeType.ALL)
Set<LecturerCourse> lecturerCourses == new HashSet<LecturerCourse>();

//all others properties Setters and getters are less relevant.

}

LecturerCourse Class:

@Entity
@Table(name = "lecturer_course")
@AssociationOverrides({
        @AssociationOverride(name = "pk.lecturer", 
            joinColumns = @JoinColumn(name = "LECTURER_ID")),
        @AssociationOverride(name = "pk.course", 
            joinColumns = @JoinColumn(name = "COURSE_ID")) })
public class LecturerCourse {

    private LecturerCourseID pk = new LecturerCourseID();

    @Column(name = "CAPACITY", nullable = false, length = 10)
    private String capacity;

    @EmbeddedId
    public LecturerCourseID getPk() {
        return pk;
    }

}

Now the Primary Key:

@Embeddable
public class LecturerCourseID implements java.io.Serializable {

    private Lecturer lecturer;
    private Course course;

    @ManyToOne
    public Stock getLecturer() {
        return lecturer;
    }

    public void setLecturer(Lecturer lecturer) {
        this.lecturer= lecturer;
    }

    @ManyToOne
    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course= course;
    }

}

now Your Main should be something like this:

Lecturer lecturer1 = new Lecturer();
Course math = new Course();
LecturerCourse lecturer1math  = new LecturerCourse();
lecturer1math.setCapacity("capacity");
lecturer1math.setLecturer(lecturer1);
lecturer1math.setCourse(math);
lecturer1.getLecturerCourses().add(lecturer1math);

//saving object
session.save(lecturer1);

You need to be sure that class marked as @Embeddable should implement Serializable marker interface.

Hope it helps.

K.C.
  • 2,084
  • 2
  • 25
  • 38
danny.lesnik
  • 18,479
  • 29
  • 135
  • 200
  • thank you very much for detailed answer. i solved the issue similar to your response. however, i wonder if there is any solution without a intermediate entity like LecturerCourse. i tried those http://stackoverflow.com/questions/4751902/adding-additional-property-to-hibernate-jointable. but it does not worked. i read the documentation http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/collections.html. still could not solve the issue. – erencan Apr 24 '12 at 16:25
  • Unfortunately, I'm not familiar with another method. I'm using the code above to create Composite primary keys and extra columns in your case. – danny.lesnik Apr 24 '12 at 16:33
  • i see. thanks again. if i can find a solution. i will also post it to you. – erencan Apr 24 '12 at 18:19
  • `lecture1math` doesn't have setters nor do you explicitly say you're ignoring them like you did for entity classes. `lecture1math` also doesn't have fields for lecturer and course so I can't assume your code is correct either. – ds011591 Aug 11 '15 at 15:46
  • @ds011591 You can get that by using transient getters: ` @Transient public Item getCourse() { return getPk().getCourse(); }` – Adam May 26 '17 at 19:25