특징

  • 두 테이블에서 같은 주키값을 사용한다.
  • 문제는 A–>B 에서 B가 A의 주키값을 사용하도록 하는 것이다. 주기를 공유하도록 설정해야 한다.

맵핑하기

  • JPA는 공유할 주키 생성기를 지원하는 표준화된 방법이 없다.
  • 하이버네이트는 커스텀 id 생성기를 위한 확장 애노테이션을 제공한다.
User.java
@OneToOne
@PrimaryKeyJoinColumn
@Cascade( { CascadeType.SAVE_UPDATE })
private Address shippingAddress;
  • @PrimaryKeyJoinColumn: JOINE을 이용한 상속구조(Table Per Subclass)에서
    하위 타입에서 상위 타입의 주키를 자신의 주키이자 외례키로 설정할 때 사용. 여기(1:1맵핑)서는 참조하는 쪽(User)의
    주키를 참조되는 쪽(Address)의 외례키로 사용하겠다는 설정이다.
Address.java
@Id
@GeneratedValue(generator = "addressIdGenerator")
@GenericGenerator(name = "addressIdGenerator", strategy = "foreign", parameters = @Parameter(name = "property", value = "user"))
@Column(name = "ADDRESS_ID")
private Long id;

@OneToOne
private User user;
  • JPA에서는 커스텀 식별자 생성기를 만들 수 없기 때문에, 하이버네이트 애노테이션을 이용해야 한다.
테스트 코드
@Test
public void userAndAddress() throws Exception {
Session session = sessionFactory.openSession();
User user = new User();

Address address = new Address();
// Address의 user 속성은 null이면 안 된다. id를 세팅해 주려고 할 때 identifierGeneration 에러 난다.
address.setUser(user);

user.setShippingAddress(address);
session.save(user);

session.flush();
session.close();
assertNotNull(user.getId());
assertNotNull(user.getShippingAddress().getId());
}
  • Fake Object인가… 저렇게 하지 않으면 에러 발생.