Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persist 1-m entities with composite primary key in hibernate

I have below 1-m relationship on entities which Mentor to Students. The mentor has composite primary key which i use as foreign key in student

@Entity
public class Mentor implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    private MentorPK id;
    private String email;
    @OneToMany(mappedBy="mentor")
    private Set<Student> students;

    public MentorPK getId() {
        return id;
    }            
    //getters and setters
}

@Embeddable
public class MentorPK implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private String add;
    //getters and setters
    //override equals and hashcode
}


@Entity
public class Student implements Serializable{
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    private String name;    

    @ManyToOne
    @MapsId("id")
    @JoinColumns({
        @JoinColumn(name="name_fk", referencedColumnName="name"),
        @JoinColumn(name="address_fk", referencedColumnName="address")
    })
    private Mentor mentor;

    //Getters and setters
}

I then persist the above as below but only the mentor is persisted where student table is empty.

How can I persist the mentor with students?

Set<Student> students = new HashSet<Student>();

Student s1 = new Student();
s1.setName("Student 1");

Student s2 = new Student();
s2.setName("Student 2");

students.add(s1);
students.add(s2);

MentorPK mpk = new MentorPK();
mpk.setAddress("C");
mpk.setName("D");

Mentor m = new Mentor();
m.setId(mpk);
m.setEmail("emaill");
m.setStudents(students);

studentManager.saveMentor(m);
like image 442
Harshana Avatar asked May 11 '15 14:05

Harshana


3 Answers

Try changing annotation of students field to

@OneToMany(mappedBy="mentor", cascade = CascadeType.PERSIST)

like image 140
Petros Splinakis Avatar answered Oct 31 '22 13:10

Petros Splinakis


When you use a composite-key, mapped as an Embeddable you need to use @EmbeddedId:

@Entity
public class Mentor {

    @EmbeddedId
    private MentorPK id;

    private String email;
    @OneToMany(mappedBy="mentor")
    private Set<Student> students;

    public MentorPK getId() {
        return id;
    }            
    //getters and setters
}

and the Student becomes:

@Entity
public class Student {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    private String name;    

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="name_fk", referencedColumnName="name"),
        @JoinColumn(name="address_fk", referencedColumnName="address")
    })
    private Mentor mentor;

    //Getters and setters
}

The @MapsId is used when both the @Id and the @ManyToOne share the same database columns, which is not your case, since you have a numeric identifier and a composite foreign-key.

like image 2
Vlad Mihalcea Avatar answered Oct 31 '22 13:10

Vlad Mihalcea


You may need to create the reference from Student to Mentor in each Student.

So in your code, after you create m you need to:

s1.setMentor(m);
s2.setMentor(m);

Otherwise Hibernate may not know what to populate columns name_fk and address_fk with.

like image 2
DuncanKinnear Avatar answered Oct 31 '22 13:10

DuncanKinnear