DB설계를 하며 들었던 의문들이 해결되어 정리해보려고 합니다.
위 ERD는 제가 프로젝트를 하며 만든 ERD인데요.
보면 테이블끼리 관계를 맺을 때 외래키가 생깁니다.
외래키를 이용해서 JOIN하기 때문입니다.
하지만 JPA에서는 어떻게 관계를 맺을까요?
관계를 맺기 위해서 외래키를 만들까요?
JPA에서는 외래키를 만들지 않습니다.
외래키가 아닌 객체를 넣습니다.
참조하는 객체 자체를 넣습니다.
JPA는 연관관계 매핑을 할 때 몇 가지 개념을 알아야합니다.
1. 방향성 - 단방향인가, 양방향인가
2. 다중성 - 1:N, N:1, 1:1, N:N
3. 연관 관계의 주인이 누구인가? - 양방향의 연관 관계는 관리의 주인이 필요합니다.
단방향 연관관계는
한쪽에만 객체를 참조하기 때문에
한쪽만 참조 객체를 가지고 있습니다.
@Entity
@NoArgsConstructor
@Data
public class Crop {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="crop_id")
private Long id;
private String name;
private String description;
}
@Entity
@Data
public class CropMonth {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="cropMonth_id")
private Long id;
@Min(1)
@Max(12)
@Column(nullable = false)
private Integer month;
@ManyToOne
@JoinColumn(name="CROP_ID")
private Crop crop;
}
추천작물은 자신이 자랄 수 있는 Month 데이터와 관계를 맺습니다.
Month를 통해서 Crop을 참조할 일은 없기 때문에 단방향으로 관계를 맺도록 하였습니다.
양방향은 서로가 서로의 객체를 참조합니다.
따라서 서로의 객체를 가지고 있습니다.
여기서 둘 중 한쪽에서는 이 외래키의 역할을 하는 객체를 관리해야 한다는 것입니다.
실제 DB에서는 양방향의 개념이 없지만
ORM에서는 양방향이 있습니다.
서로 연관되었다는 것 = 서로를 찾을 수 있다 = 서로의 객체를 가지고 있어야 한다.
하지만 실제 DB에서는 양방향의 개념이 없다. 실제는 한쪽만 외래키를 가지고 있다.
결국 ORM 매핑 시 연관 관계의 주인을 정해야 한다.
로 귀결되는거 같습니다.(개인 생각입니다.)
그렇다면 연관관계의 주인은 누구일까요?
바로 일대다에서 "다"에 해당하는 객체가 연관관계의 주인이 됩니다.
따라서 주인을 표시하는 방법과 주인이 아닌 것을 표시하는 방법이 정해져 있습니다.
@Entity
@NoArgsConstructor
@Data
public class Post {
...
@OneToMany(mappedBy = "post")
private List<GardenPicture> gardenPicture = new ArrayList<>();
...
}
@Entity
@NoArgsConstructor
@Data
public class GardenPicture {
...
//연관관계 주인
@ManyToOne
@JoinColumn(name="post_id")
private Post post;
...
}
따라서 저는 다에 해당하는 GardenPicture(사용자가 등록한 텃밭 사진)을 연관관계의 주인으로 하였고 주인을 표시할 때는 JoinColumn(name="관계 상대의 id")를 이용합니다.
반대로 관계를 맺게 되는 주인이 아닌 상대는 내가 주인이 아니라는 표시를 해야하는데 maapedBy를 이용하여 자신이 주인이 아니고 주인은 "post"임을 나타냅니다.
또한 DB에서는 JOIN을 통해 데이터의 관계가 맺어지지만 ORM은 객체를 통해 일어나기 때문에 일대다에서 일에 속하는 객체는 상대 객체를 List로 받아야 합니다.
결과를 볼까요?
JPA를 사용하여 DB 테이블을 만들었을 때
GardenPicture는 주인이기 때문에 Post_id를 외래키로 가지고 있지만
Post에는 없습니다.
앞서 말했듯이 DB 상에서는 양방향의 개념이 없습니다.
그냥 외래키로 JOIN하면 서로를 찾아갈 수 있기 때문입니다.
하지만 ORM 매핑을 하면 서로의 객체를 가지고 있지 않는한 서로를 찾아갈 수 없죠
따라서 서로의 객체를 가지고 있되 누군가 외래키를 관리해야합니다.
프록시에 대한 , 즉시 로딩, 지연로딩
아래 글 참조해서 보기
https://ultrakain.gitbooks.io/jpa/content/chapter8/chapter8.1.html