스프링 연관관계 매핑

CinnamonTree·2022년 2월 2일
0

스프링

목록 보기
1/2

객체가 지향하는 패러다임과 관계형DB가 지향하는 패러다임의 불일치를 어떻게 해결할 것인가?

객체는 레퍼런스 (ex. A.getB()) 로 따라가지만
테이블은 외래키 값을 이용한다. (ex. A테이블의 id)
따라서 객체의 참조와 테이블의 외래키, 이 둘을 매핑하는 법을 배워야 한다.

관계형 DB 설계 시 알아야 될 단어

  • Multiplicity:다중성(일대일, 다대다...)
  • 연관관계의 주인

단방향 연관관계

객체를 테이블 중심(데이터 중심)으로 모델링하면? (연관관계 없음, 객체의 참조 없이 외래키를 그대로 사용할 때)

ex) A객체가 B객체의 id값을 속성으로 가지고 있을 때

  • 테이블은 외래키로 조인
  • 객체는 참조 사용 객체

=> 협력관계를 만들 수 없다. 연관관계가 없기 때문에 어떤 작업이 필요할때마다 JPA를 통해 DB에 계속 요청해야 한다.

객체의 참조와 테이블 외래키 매핑 (@JoinColumn, @ManyToOne 단방향 매핑)

ex) A가 B의 참조값을 속성으로 가지고 있을 때
=> 참조를 사용하여 연관 객체를 바로 조회 가능

양방향 연관관계

A객체와 B객체가 의미가 연관되어있을 때, 테이블 연관관계에 외래키 하나만 가지게 하여도 외래키 Join 연산으로 양쪽으로 참조가 가능하다.
(테이블 연관관계에는 방향이란 개념이 없다)

@OneToMany(mappedBy='b')
@ManyToOne + @JoinColumn(name='b_id')

객체와 테이블이 관계를 맺는 차이

객체 연관관계:

  • A객체-> B객체 단뱡향 연관관계 1개
  • B객체-> A객체 단뱡향 연관관계 1개

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생성 라이브러리를 사용할 때

  • 따라서 Controller에서 Entity를 바로 반환하지 말고 DTO를 사용하여 반환하도록 하자. : 무한루프, 엔티티 변경할 수도 있음.

사실 JPA매핑 설계할 때 양방향 매핑이 아닌 단방향 매핑으로 설계를 완료하여야 한다. 실무에서는 JPQL에서 양방향으로 탐색할 일이 많아 이때 양방향 매핑을 사용하지만, 단방향 매핑을 잘 하고 양방향은 필요할 때 추가하면 된다.

연관관계의 주인을 결정하는 기준: 외래키의 위치

0개의 댓글