객체가 지향하는 패러다임과 관계형DB가 지향하는 패러다임의 불일치를 어떻게 해결할 것인가?
객체는 레퍼런스 (ex. A.getB()) 로 따라가지만
테이블은 외래키 값을 이용한다. (ex. A테이블의 id)
따라서 객체의 참조와 테이블의 외래키, 이 둘을 매핑하는 법을 배워야 한다.
관계형 DB 설계 시 알아야 될 단어
ex) A객체가 B객체의 id값을 속성으로 가지고 있을 때
=> 협력관계를 만들 수 없다. 연관관계가 없기 때문에 어떤 작업이 필요할때마다 JPA를 통해 DB에 계속 요청해야 한다.
ex) A가 B의 참조값을 속성으로 가지고 있을 때
=> 참조를 사용하여 연관 객체를 바로 조회 가능
A객체와 B객체가 의미가 연관되어있을 때, 테이블 연관관계에 외래키 하나만 가지게 하여도 외래키 Join 연산으로 양쪽으로 참조가 가능하다.
(테이블 연관관계에는 방향이란 개념이 없다)
@OneToMany(mappedBy='b')
@ManyToOne + @JoinColumn(name='b_id')
객체 연관관계:
DB입장:
Foreign키 하나로 연관관계가 해결됨
이 상황에서,
하나의 객체를 연관관계의 주인으로 정해야 한다.
연관관계의 주인이 외래키를 등록하고 수정하며, 주인이 아닌쪽은 읽기만 가능하다.
mapped'By' 라는 이름에서 알 수 있듯이 연관관계의 주인 속성에는 mappedBy를 사용하지 않는다.
보통 외래키가 있는 곳을 주인으로 정한다.
DB입장에서는 1:N관계에서 보통 외래키가 있는 쪽이 N이다. (따라서 보통 @ManyToOne인 컬럼)
주의!: 연관관계의 주인이 아닌 컬럼을 업데이트 해도 저장이 되지 않는다.
=> 읽기 전용이어서...
그럼에도 불구하고 양방향 연관관계 사용 시 한쪽(주인)에만 값을 입력해서는 안되고 양쪽 모두에 값을 입력해야 한다.
연관관계의 주인이 아닌 객체의 값을 조회 시 중간에 flush 와 clear를 하지 않으면 영속성 컨텍스트의 1차캐시에서만 그대로 조회가 되기 때문에 순수한 객체로만 조회가 된다.
따라서 항상 양쪽에 값을 설정하는데, 보통 하나만 설정하고 깜박하는 경우가 많으므로, 주인의 값을 설정하는 set객체 매서드에 연관관계 편의 메서드를 생성하자.
setB(B b){
this.b = b;
b.getAs().add(this); //추가
}
양쪽 객체의 set메서드 모두에 설정이 가능한데, 개발 상황마다 다르므로 잘 고려하자.
toString(), lombok, JSON생성 라이브러리를 사용할 때
사실 JPA매핑 설계할 때 양방향 매핑이 아닌 단방향 매핑으로 설계를 완료하여야 한다. 실무에서는 JPQL에서 양방향으로 탐색할 일이 많아 이때 양방향 매핑을 사용하지만, 단방향 매핑을 잘 하고 양방향은 필요할 때 추가하면 된다.
연관관계의 주인을 결정하는 기준: 외래키의 위치