1

I am implementing one to one (one Employee<-> one Mobile) relationship in hibernate as follows. This code works fine, but as this is one to one relationship, assigning same mobile number to emp1 and emp2 should have created problem (it violates relationship) but code is accepting and adding 2 emps with same mobile (Confirmed from Database tables). Why is hibernates one to one relationship like one mobile<->many employees? My Code: @Entity

public class Employee {
    @Id  @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    private String name;
    @OneToOne
    private Mobile mobile;
    //...rest of the code
}
@Entity
public class Mobile {
    @Id @GeneratedValue
    private int id;
    private long number;
    //...rest of the code
}
Test Client main(...){
    Mobile mobile = new Mobile(9999999999L);
    Employee emp1 = new Employee("Raja");
    Employee emp2 = new Employee("Raja");
    emp1.setMobile(mobile);
    emp2.setMobile(mobile);// VIOLATING 1-1 RELATIONSHIP
    //...REST OF THE COMMON CODE
    session.save(mobile);
    session.save(emp1);
    session.save(emp2);
    session.getTransaction().commit();
}

DATABASE SHOWS BOTH EMP RECORDS WITH SAME MOBILE NUMBER (VIOLATION OF 1-1)

Kedar Tokekar
  • 418
  • 3
  • 10
  • Do you use hibernate property `hibernate.hbm2ddl.auto` for generating your tables ? hibernate add automatically the unicity constraint when it is responsible of tables creation otherwise you have to add it manually. – Abass A Jul 18 '17 at 08:17
  • possible duplicate of https://stackoverflow.com/questions/8968294/why-onetoone-is-allowing-duplicate-associations – Sangam Belose Jul 18 '17 at 08:49
  • Yes this is similar to the question in comment link. Apologies for repeat – Kedar Tokekar Jul 18 '17 at 09:40

1 Answers1

0

For one to one relations, you should always make sure that you have a unique constraint on your database (either generated by hibernate or manually created).

Hibernate won't check it because it would require to collect extra data every time to do the check. The database can do it more efficiently. To do the check, hibernate would have to do an extra query. And if the database is configured correctly that extra query would cost time and resources without any gain.

If you don't have unique constraints and you define the relation bidirectional, you can get even more trouble. Hibernate will save the conflicting records without complaining as you already discovered. And it would become impossible for hibernate to use the relation starting from the object on the other side (getting the Employee via the Mobile in your case). If mobile would be configured to get it's related employee eagerly, it would become impossible to get the mobile in memory after both employee's where saved.

  • Thanks Stefan for explaining it well. So tell me whether I understood it correctly - "Its not Hibernates responsibility to take care of one/many to one/many, it should be through the model objects relationships and its just an input provided to hibernate so that it can take certain things for granted and optimize its implementation". before getting you nice explanation I also tried following. – Kedar Tokekar Jul 18 '17 at 09:27
  • sorry for earlier incomplete comment. - Added Employee reference to Mobile side with @OneToOne annotation to make it bidirectional. resulting in both tables with each others foreign keys. Still code could be messed up by assigning emp1, emp2 to same mobile (though it's wrong implementation hib ignored) – Kedar Tokekar Jul 18 '17 at 09:36
  • It's hibernates responsibility to map your object model correctly to a database scheme. The consistency of the data in your database is a different thing. – Stefan Mondelaers Jul 18 '17 at 10:10
  • Making the relation bidirectional means you define the relation on the other side also with OneToOne but with MappedBy field specified on the annotation. This way it doesn't need an extra db field and there will still be only one foreign key in your database. Without MappedBy it wouldn't be a bidirectional relation but 2 single direction relations and you would even have more work yourself to keep those consistent. – Stefan Mondelaers Jul 18 '17 at 10:11
  • And yes, whatever you do, you always can mess up by assigning the same mobile to 2 employees unless you check it yourself using the other direction of the relation or you define a unique constraint. But the unique constraint will always be more efficient. – Stefan Mondelaers Jul 18 '17 at 10:11
  • Thanks. that was very good explanation. In that case I feel we should implement the constraints programatically in Object model as well instead of depending upon DB constraints as Object model being in different layer need not be at the mercy of DB constraints (it may be optionally using other persistence mechanisms). But thanks for resolution to the point. – Kedar Tokekar Jul 18 '17 at 13:56