Reputation: 2209
I am using Hibernate 4.3.
I have created below entity for Student
.
@Entity
@Table(name="STUDENT")
public class Student {
public Student(){
}
public Student(String name, Set<Course> courses){
this.studentName = name;
this.courses = courses;
}
@Id
@GeneratedValue
@Column(name="STUDENT_ID")
private long studentid;
@Column(name="STUDENT_NAME")
private String studentName;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="STUDENT_COURSE",
joinColumns=@JoinColumn(name="STUDENT_ID"),
inverseJoinColumns=@JoinColumn(name="COURSE_ID")
)
private Set<Course> courses = new HashSet<Course>(0);
//Getter Setter Methods
}
And another entity is Course
.
@Entity
@Table(name = "COURSE")
public class Course {
public Course(String courseName) {
this.courseName = courseName;
}
@Id
@GeneratedValue
@Column(name = "COURSE_ID")
private long courseID;
@Column(name = "COURSE_NAME")
private String courseName;
@ManyToMany(mappedBy="courses")
private Set<Student> students = new HashSet<Student>(0);
//Getter Setter Methods
// I have added equality and hashcode check below
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Course)) {
return false;
}
Course anotherCourse = (Course) obj;
// return this.courseName == anotherCourse.courseName;
return (this.courseName == null)? anotherCourse.courseName == null : this.courseName.equals(anotherCourse.courseName);
}
@Override
public int hashCode() {
return courseName.hashCode();
}
}
In my application I have code as:
// Configuration and Session creation for Hibernate
Set<Course> courses = new HashSet<Course>();
courses.add(new Course("Maths"));
Student st1 = new Student("ABCD", courses);
session.save(st1);
courses.add(new Course("Physics"));
Student st2 = new Student("EFGH", courses);
session.save(st2);
In the above case it inserts invalid data, as both courses for both the students. Which is incorrect, but as in Java the object is same so that is correct. But I want the courses to map as defined above. How to handle this at Hibernate end ?
I tried another option as:
Set<Course> courses = new HashSet<Course>();
Set<Course> courses1 = new HashSet<Course>();
courses.add(new Course("Maths"));
Student st1 = new Student("ABCD", courses);
session.save(st1);
courses1.add(new Course("Maths"));
courses1.add(new Course("Physics"));
Student st2 = new Student("EFGH", courses1);
session.save(st2);
But this time it created two different courses for same courseName = "Maths"
.
Even if I have created a equals
and hashCode
method implementation.
Need solution, how to handle this in Hibernate.
Upvotes: 1
Views: 113
Reputation: 2209
I have found the solution for the issue as below:
Course maths = new Course("Maths");
Course physics = new Course("Physics");
Set<Course> courses = new HashSet<Course>();
Set<Course> courses1 = new HashSet<Course>();
courses.add(maths);
Student st1 = new Student("ABCD", courses);
session.save(st1);
courses1.add(maths);
courses1.add(physics);
Student st2 = new Student("EFGH", courses1);
session.save(st2);
In this I have created objects for Course
and used the same object in both set. So in the database it is created only one row entry for course Maths
.
Thus solved the purpose. Thank you.
Upvotes: 1
Reputation: 426
I believe your issue comes from the implementation of your equals()
method in the Course
class
Indeed, when you do this :
return this.courseName == anotherCourse.courseName;
, you compare the memory reference of this.courseName
with the courseName
of anotherCourse
.
Instead, you should use the equals() method, like this :
return this.courseName.equals(anotherCourse.courseName);
, which compares the string content instead of the reference.
In your second attempt, since you create 2 objects (with the same value), and since your implementation of equals()
in Course
compares the reference (the memory address) of the objects instead of their content, Hibernate believes those are different.
Upvotes: 1