객체의 참조와 테이블의 외래 키를 매핑하는법을 알아야 한다.
용어
1. 방향: 단방향, 양방향
2. 다중성: 다대일, 일대다, 일대일, 다대다
3. 연관관계의 주인: 객체 양방향 연관관계는 관리 주인이 필요
테이블은 외래 키로 조인을 사용하여 연관된 테이블을 찾는 반면에 객체는 참조를 사용해서 연관된 객체를 찾는다.
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
//Getter, Setter
}
멤버는 하나의 팀을 가질 수 있고 팀은 여러명의 멤버를 가질 수 있다.
따라서 멤버 엔티티에서는 팀을 @ManyToOne으로 해주고 (멤버 : 팀 = N : 1) 조인 할 컬럼을 팀 아이디로 설정해주면 된다. @JoinColumn(name = "TEAM_ID")
양방향으로 객체에서 참조하도록 하여도 테이블에서는 변화가 없다. 테이블의 연관관계는 외래키 하나로 양방향이 다 있는 것이기 때문이다.
mappedBy는 무엇일까
mappedBy를 이해하려면 객체와 테이블간에 연관관계를 맺는 차이를 이해해야 한다.
객체와 테이블이 관계를 맺는 차이
객체는 연관관계가 2개이다.
멤버 -> 팀 연관관계 1개
팀 -> 멤버 연관관계 1개
양방향 관계가 아니라 단방향 연관관계가 2개가 있는 것이다.
따라서 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야 한다.
// A -> B : a.getB()
class A {
B b
}
// B -> A : b.getA()
class B {
A a
}
테이블의 연관관계는 1개이다.
fk(외래키)하나로 조인하여 양쪽의 연관관계를 알 수 있다.
이런 차이점 때문에 멤버의 팀값을 바꿨을 때 외래키 값이 업데이트 되어야 하는지, 팀에있는 멤버s 값을 바꿨을 때 외래키 값이 업데이트 되어야 하는지의 딜레마가 온다.
둘 중 하나로 외래 키를 관리해야 한다. > 주인을 정해야 한다
객체의 두 관계중 하나를 연관관계의 주인으로 지정
연관관계의 주인만이 외래키를 관리
주인이 아닌 쪽(mappedBy)은 읽기만 가능(readOnly)
주인은 mappedBy 속성 사용x
주인이 아니면 mappedBy 속성으로 주인 지정
fk(외래키)가 있는 곳을 연관관계의 주인으로 해야한다.
DB 입장에서 보면 외래키가 있는 곳이 무조건 N(다)이다. (없는 곳이 1)
즉, N:1일 경우에 N이 있는 곳에 주인을 두면 된다.
(양방향일 경우 1에는 mappedBy를 두면 된다.)
연관관계 주인에 값을 입력하지 않음
연관관계의 주인이 아닌, 역방향에만 값을 넣어주면 readOnly라서 반영이 안된다.
그래도 양쪽에 값을 넣어주는것이 맞다.
양쪽으로 값을 넣어주지 않으면 중간에 flush하고 clear해주지 않는다면 1차 캐시에서 다시 들고오기 때문에 mappedBy된 곳에는 값이 들어가지 않은 상태이다.
객체 지향적으로 봤을 때도 양쪽에 값을 넣어주는 것이 맞고, 후에 테스트를 할 때에도 양쪽에 값을 넣어주는 것이 편하다.
양쪽에 모두 값을 넣어주기 위해서는 연관관계 편의 메소드를 작성해서 쓰는 것이 더 편하다.
무한 루프
toString(), lombok, JSON 생성 라이브러리
JSON의 경우 컨트롤러에서 직접 엔티티를 보내는 경우 무한루프가 발생한다. 따라서 컨트롤러에서는 엔티티를 반환하지 않도록하고 dto로 변환을 해서 반환하도록 설계해야 한다.
lombok에서 toString만드는 것은 쓰지 말도록 해야한다.
설계 시에 단방향 매핑으로 설계를 끝내야 한다.
양방향 매핑은 반대 방향으로 조회 기능이 추가되는 것일 뿐
양방향 매핑은 필요할 때 추가하면 된다. (테이블에 영향을 주지 않기 때문에)