Search code examples
hibernatehibernate-mapping

Bi-directional one-to-one mapping


@Entity
@Table(name="Instructor")
public class Instructor {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
    
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "detail_id")
    private InstructorDetails detail;
    
    @Column(name="name")
    private String name;
}

This is my first entity class, this class does contain the required setters and getters and constructors, I have not included them as they would make the question lengthy

@Entity
@Table(name="InstructorDetails")
public class InstructorDetails {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "did")
    private int did;
    
    @OneToOne(mappedBy = "detail",cascade = CascadeType.ALL)
    private Instructor instructor;
    
    @Column(name = "address")
    private String address;
    
    @Column(name = "course")
    private String course;
    
    @Column(name = "hobby")
    private String hobby;
    
    @Column(name = "dept")
    private String dept;
}

This is my second entity class, this class does contain the required setters and getters and constructors, I have not included them as they would make the question lengthy

As you can see I have tried performing bi-directional one-to-one mapping, and I have clearly mentioned cascade=CascadeType.ALL, which means all operations that occur in one table are cascaded to the other, I have attempted to perform a bi-directional mapping by including @OneToOne(mappedBy = "detail", cascade = CascadeType.ALL)

The problem here is

Session session = sf.getCurrentSession(); 
session.beginTransaction();

InstructorDetails detail=new InstructorDetails("bengaluru", "Java", "Guitar", "development");
Instructor instructor=new Instructor("john",detail);

session.save(instructor);
session.getTransaction().commit();

This code pushes the details into both Instructor and InstructorDetails table, but if

Session session = sf.getCurrentSession(); 
session.beginTransaction();

Instructor instructor=new Instructor();
instructor.setName("Sam");
InstructorDetails detail=new InstructorDetails("bengaluru", "Java", "Guitar", "development");
detail.setInstructor(instructor);
    
session.save(detail);
session.getTransaction().commit();

This code pushes data into only InstructorDetails table and Instructor table is not updated with instructor details, this means the mapping is uni-directional

All the CRUD operations on Instructor cascade to InstructorDetails, but I am not able achieve the vice-versa, kindly help me here , how do I ensure all the crud performed on InstructorDetails affects Instructor too


Solution

  • As it is stated in the hibernate documentation:

    Whenever a bidirectional association is formed, the application developer must make sure both sides are in-sync at all times.

    So, you should correct your code in the following way:

    Session session = sf.getCurrentSession(); 
    session.beginTransaction();
    
    Instructor instructor = new Instructor();
    instructor.setName("Sam");
    InstructorDetails detail = new InstructorDetails("bengaluru", "Java", "Guitar", "development");
    
    // sync both side of association
    detail.setInstructor(instructor);
    instructor.setDetail(detail);
    
    session.save(detail);
    session.getTransaction().commit();