Tam's Blog

<- Quay về trang chủ

Mapping 1-1 relationship in hibernate

Context

Solution

When we model relationship as regular bidirectional one-to-one relationship like two entity below:

public class QuizEntity {

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

  @OneToOne(fetch = LAZY, mappedBy = "quiz", optional = false)
  private QuizResultEntity result;

  // other fields
}

public class QuizResultEntity {

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

  @OneToOne(fetch = LAZY, optional = false)
  @JoinColumn(name = "quiz_id")
  private QuizEntity quiz;

  // other fields
}

and fetch an entity of QuizEntity type, hibernate will trigger an additional query to check whether the associated QuizResultEntity object existing or not to provide appropriate strategy to initialize relationship. If QuizResultEntity object exists, hibernate will create a proxy, otherwise this field is set to null.

So if we add optional = false properties to @OneToOne annotation, will hibernate trigger additional query?

Unfortunately, based on [1], hibernate will still trigger additional query because the identifier of QuizResultEntity is unknown.

Query log:

select q1_0.id from quiz q1_0 where q1_0.id=?
select q1_0.id,q1_0.quiz_id from quiz_result q1_0 where q1_0.quiz_id=?

-> Use @OneToOne mapping with @MapIds at QuizResultEntity side can solve this problem. This will work because at QuizEntity side, hibernate knows the ID of associated QuizResult entity when it queries data.

public class QuizResultEntity {

  @Id
  // Note: we don't use auto generate strategy here.
  // @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @OneToOne(fetch = LAZY)
  @MapsId
  @JoinColumn(name = "quiz_id")
  private QuizEntity quiz;

  // other fields
}

Query log:

select q1_0.id from quiz q1_0 where q1_0.id=?

Example source code: https://github.com/dntam00/learning-spring/tree/master/one-to-one