Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate: @OneToOne not producing "one to one" relationship in database

I'm relatively new to JPA and Hibernate and am trying to see how the @OneTo One annotation works, let's say I have an entity "Task" with the following relation:

 @OneToOne
    @JoinColumn(name = "manager_id")
    private Manager manager;

And there's the entity "Manager":

@Entity
@Table(name = "manager")
public class Manager {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;
 private String name;

 public Manager() {
 }

When I run the test file along with the "hibernate.hbm2ddl.auto" set to "update" I get a Many to One relation in the database (as you can see, there is no unique constraint of any kind that'd make it a one to one relation):

CREATE TABLE IF NOT EXISTS `timesheet`.`task` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `completed` BIT(1) NOT NULL,
  `description` VARCHAR(255) NULL DEFAULT NULL,
  `manager_id` BIGINT(20) NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  INDEX `FK3635851B178516` (`manager_id` ASC),
  CONSTRAINT `FK3635851B178516`
    FOREIGN KEY (`manager_id`)
    REFERENCES `timesheet`.`manager` (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

To be sure of this I tried adding two records with the same manager id and were indeed added, I also tried setting the unique constraint like "@Table(name = "Task",uniqueConstraints = @UniqueConstraint(columnNames =..." but no luck. So Why is this happening and what's exactly the pros of using @OneToOne annotaion if no application logic is applied to validate this?

Also, Is there any chance that Hibernate is not able to do the DDL generation properly? (I know that generation of schemas through hibernate is only meant for testing)

like image 837
Daniel Arechiga Avatar asked Feb 07 '23 04:02

Daniel Arechiga


1 Answers

In a unidirectional relationship you will get the expected unique constraint if you mark it as "optional=false". You also get it if you set the join column explicitly as unique, of course.

So either

@OneToOne(optional=false)
    @JoinColumn(name = "manager_id")
    private Manager manager;

or

@OneToOne
    @JoinColumn(name = "manager_id", unique=true)
    private Manager manager;

So why do you need to mark it as not optional? My guess is that, when a value is optional, the column can contain many null values, but in many databases this can not be done when a unique constraint is present. You can do it in MySQL though, so maybe the Hibernate generator is not taking the database into account in this case (a bug?). See a discussion about MySQL handling of nulls here.

like image 169
xtian Avatar answered Feb 13 '23 04:02

xtian