[JPA] 다양한 연관관계 매핑

김용현·2023년 12월 21일
0

JPA

목록 보기
5/12
post-thumbnail

본 포스트는 김영한 님의 자바 ORM 표준 JPA 프로그래밍 강의를 토대로 작성하였습니다.

데이터 베이스 외래 키 연결 관계

관계형 DB를 사용할 때 두 테이블 간 어떠한 관계를 맺고 있느냐에 따라 유형이 달라진다.

  • 1:1 (일대일 관계)
  • 1:N (일대다 관계)
  • N:1 (다대일 관계)
  • N:N (다대다 관계)

다음과 같이 관계를 나눌 수 있다.

JPA에서 DB 연관 관계에 따라 어떻게 매핑이 되는지 하나씩 알아보자.

일대일 관계

테이블 간 하나씩 연결되는 관계로 주 테이블에서 외래 키를 갖고 있는 단방향이다.
주 테이블이란 주로 사용되는 테이블을 말하며 반대쪽은 대상 테이블이라고 한다.

매핑 어노테이션은 @OneToOne이다.
코드로 보면,

//Member Entity 중 일부
@OneToOne
@JoinColumn(name = "UNIQUE_LOCKER_ID", unique = true)
private Locker locker;
//Locker Entity
@Entity
public class Locker {
	@Id
	@GeneratedValue
	@Column(name = "LOCKER_ID")
	private Long id;
	private String name;
}

다음과 같이 잘 생성된 것을 알 수 있다.

그렇다면 양방향은 어떻게 할까. 이후에 나올 다대일과 동일하게 대상 테이블(여기서는 Locker)에 매핑할 객체를 추가한다.(Member객체 추가) 이후 mappedBy 속성을 적용해주면 된다.
mappedBy 값은 매핑 반대편 필드 이름(변수 이름)
코드로 보자

@Entity
public class Locker {
    @Id
    @GeneratedValue
    @Column(name = "LOCKER_ID")
    private Long id;
    private String name;
    @OneToOne(mappedBy = "locker")
    private Member member;
}

바뀐 건 Member 객체 추가와 어노테이션 밖에 없다.

일대다 관계

일대다 관계는 가능하면 사용하지 않는 것이 좋다고 한다. 이유는 엔티티가 관리하는 외래 키가 다른 테이블에 있다. 다시말해 관리하는 엔티티의 외래 키 값을 바꾸면 다른 테이블에 쿼리가 나가게 되어 개발자가 혼동할 수 있다.

따라서 간단하게 특징만 알아보고 넘어가자.

다대일 관계

가장 많이 사용되는 관계 형태라고 한다.

기본적으로 외래키를 들고 있는 테이블이 연관 관계의 주인이 되며, 이에 맞게 어노테이션을 붙이면 된다. 코드로 알아보자.

//Member Entity 중 일부
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
//Team Entity
@Entity
public class Team {
    @Id
    @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

Member가 Many 이고 Team이 One이므로 @ManyToOne 어노테이션을 붙인다.
Member 테이블이 Team 외래 키를 갖고 있으므로 Member가 연관관계의 주인이 된다.

다대일 양방향에 대해서도 알아보자.

크게 다를 건 없다. Team Entity에 List members 필드가 추가되었다.
코드로 알아보자.

//Team Entity 중 일부
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();

다음과 같이 다대일의 반대편이므로 일대다를 붙여준다. 또한 mappedBy 속성을 주어 매핑 반대편의 필드 이름을 적어준다. 이렇게 양방향이 되면 연관관계 주인이 아닌 Team은(mappedBy가 붙어있는 것이 주인이 아니라고 생각해도 될 것 같다.) 외래 키 값을 조회만 가능하다.

다대다

테이블 상에서 객체처럼 양 쪽 모두 반대편의 값들을 여러개 가질 순 없다. 따라서 연결 테이블을 만들어 매핑된 id 값들을 저장함으로써 구현한다.

다대다 매핑도 실무에서는 크게 사용되지 않는다고 한다.
이유는 연결 테이블에 다른 컬럼을 넣을 수 없기 때문인데, 실제 비즈니스에서는 연결 테이블로 연결만 하고 끝나는 경우가 없다고 한다. 따라서 해결책으로 연결 테이블을 하나의 Entity로 승격시켜 사용하는 방법이 있다. 즉, 어차피 연결할 거 Entity로 만들어서 다른 컬럼도 가질 수 있게 매핑해서 쓰자의 의미인 것 같다.

profile
평생 여행 다니는게 꿈 💭 👊 😁 🏋️‍♀️ 🦦 🔥

0개의 댓글