연관관계
연관 관계 정의 규칙
•
방향 : 단방향, 양방향
•
연관 관계의 주인 : 양방향일 때, 연관 관계에서 관리 주체
•
다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M)
방향
데이터 베이스 → 외래 키 하나로 양 쪽 테이블 조인이 가능( 단방향 양방향 나눌 필요 X)
객체 → 참조용 필드가 있는 객체만 다른 객체를 참조하는 것이 가능
두 객체 모두가 각각 참조용 필드를 갖고 참조하면 양방향 관계
엄밀하게는 양방향 관계는 없고 두 객체가 단방향 참조를 각각가져서 양방향 관계처럼 사용하고 말하는 것
양방향의 사용
객체 입장에서 양방향 매핑을 했을 때 오히려 복잡해질 수 있다
그리고 다른 엔티티들도 불필요한 연관관계 매핑으로 인해 복잡성이 증가할 수 있다.
기본적으로 단방향 매핑으로 하고 나중에 역방향으로 객체 탐색이 꼭 필요하다고 느낄 때 추가
연관 관계의 주인
두 객체가 단방향 관계 2개를 맺을 때, 연관 관계의 주인을 지정해야 한다
테이블에 대한 실질적인 관계가 어떤 것인지 jpa에게 알려주는 과정
연관 관계의 주인은 연관 관계를 갖는 두 객체 사이에서 조회, 저장, 수정, 삭제를 할 수 있지만, 연관 관계의 주인이 아니면 조회만 가능합니다.
외래키가 있는 곳을 연관 관계의 주인으로 아닌 곳은 mappedBy 속성 지정
다중성 - 다대일(N:1)
시나리오
하나의 게시판(1)에는 여러 게시글(N)을 작성할 수 있습니다.
하나의 게시글은 하나의 게시판에만 작성할 수 있다.
게시글(Post)과 게시판(Board)은 다대일 관계를 갖습니다.
(게시글(Post)N : 게시판(Board)1)
Plain Text
복사
외래 키는?
게시글(N)이 관리한다(일반적으로 데이터베이스는 무조건 다(N)쪽이 외래 키를 갖는다)
단방향
@Entity
public class Post {
@Id @GeneratedValue
private Long id;
private String title;
@ManyToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
}
@Entity
public class Board {
@Id @GeneratedValue
private Long id;
private String title;
}
Java
복사
양방향
@Entity
public class Post {
@Id @GeneratedValue
private Long id;
private String title;
@ManyToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
}
@Entity
public class Board {
@Id @GeneratedValue
private Long id;
private String title;
@OneToMany(mappedBy = "board")
List<Post> posts = new ArrayList<>();
}
Java
복사
mappedBy 를 통해 연관관계의 주인 지정
이름은 변수명을 따라 지정한다
수업시간 예시
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
private String userName;
@ManyToOne
@JoinColumn(name = "hospital_id")
private Hospital hospital;
}
public class Hospital {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String roadNameAddress;
private String hospitalName;
@OneToMany(mappedBy = "hospital", fetch = FetchType.LAZY)
private List<Review> reviews;
}
Java
복사
한 개의 병원(1)은 여러개의 리뷰(N)를 갖는다
Review(N)(연관 관계의 주인) : Hospital(1)
FetchType.LAZY : 실무에서 LAZY를 사용한다
다중성 - 일대다(1:N)
연관관계의 주인이 1 인 것
성능이슈는 크지 않으나 유지보수 차원에서 다대일을 사용하는 것이 편하다
공식적으로 존재하지 않는다
실무에서 거의 사용하지 않음!
다중성 - 일대일(1:1)
주 테이블에 외래키를 넣을 수도 있고, 대상 테이블에 외래키를 넣을 수도 있습니다.
시나리오
게시글(Post)에 첨부파일(Attach)을 반드시 1개만 첨부할 수 있다.
Java
복사
단방향
@Entity
public class Post {
@Id @GeneratedValue
private Long id;
@Column(name = "TITLE")
private String title;
@OneToOne
@JoinColumn(name = "ATTACH_ID")
private Attach attach;
//... getter,setter
}
@Entity
public class Attach {
@Id @GeneratedValue
@Column(name = "ATTACH_ID")
private Long id;
private String name;
}
Java
복사
양방향
@Entity
public class Attach {
@Id @GeneratedValue
@Column(name = "ATTACH_ID")
private Long id;
private String name;
@OneToOne(mappedBy = "attach")
private Post post;
}
Java
복사
외래키는?
테이블은 보통 변경이 어렵기 때문에 신중히 결정해야 한다
객체지향 개발자 선호 - 테이블(Post)에 두는 것을 선호
데이터베이스 개발자 선호 - 전통적인 데이터베이스 개발자 선호
다중성 - 다대다(N:M)
실무에서 거의 사용하지 않음!
중간테이블이 숨겨져 있어서 자기도 모르는 복잡한 Join Query 발생 가능하다
연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야함