본 포스트는 김영한 님의 자바 ORM 표준 JPA 프로그래밍 강의를 토대로 작성하였습니다.
관계형 DB를 사용할 때 두 테이블 간 어떠한 관계를 맺고 있느냐에 따라 유형이 달라진다.
다음과 같이 관계를 나눌 수 있다.
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로 만들어서 다른 컬럼도 가질 수 있게 매핑해서 쓰자의 의미인 것 같다.