[JPA] 연관관계 설정 고민
- [ Backend ]/Spring DB, JPA
- 2023. 5. 7.
1. 일대일 매핑에서 어느쪽을 연관관계의 주인으로 하는것이 맞는가?
반드시 다(N)쪽이 fk를 가져 연관관계의 주인이 되는 다대일 관계와 다르게, 일대일 매핑의 경우 어느쪽이 fk를 갖게 하여 주인으로 설정하든 기능적으로 문제가 없다. 어느쪽을 연관관계의 주인으로 설정하는 것이 좋을까?
일대일 매핑에서도 주 테이블(자주 접근하는 테이블)과 대상 테이블이 존재하는데, 일반적으로 주 테이블에 외래키가 있는 것이 좋다고 느꼈다.
내가 진행했던 프로젝트 중에, feature별로 고유 이름을 가지게 하고, 사용자들이 그 고유 이름을 기준으로 즐겨찾기를 등록하여 feature가 변경되거나 삭제되더라도 고유 이름에 대한 즐겨찾기는 유지되게 하는 요구사항이 있었다.
@Entity
@Table(name = "features")
class Feature(
...
@field:OneToOne(fetch = FetchType.LAZY)
@field:JoinColumn(name = "feature_name_id")
val featureName: FeatureName,
...
) : BaseTimeEntity()
@Entity
@Table(name = "feature_names")
class FeatureName(
...
@field:OneToOne(mappedBy = "featureName", orphanRemoval = false)
var feature: Feature?
...
) : BaseTimeEntity()
고유 이름을 저장하기 위해서, feature_name이라는 엔티티를 만들어 db에 고유 이름을 저장할 수 있게끔 했는데, 이때 잠시 fk를 어디에 저장할 것인가에 대한 고민을 했었다. 결론은 자주 사용하는 주 테이블인 feature에 fk를 저장하고, orphanRemoval = false속성을 설정하여 feature가 삭제되더라도 반대 feature_names 테이블의 데이터는 유지되게끔 하였다.
위와 같이 논리적인 이유도 있지만, 가장 큰 이유는 데이터의 삽입이 연관관계의 주인쪽에서만 가능하기 때문이다. 즉, 외래키(featurename_id)를 수정하는 동작은 feature에서 이루어져야 하며, feature에서 고유 이름을 저장하는 것은 가능하지만 고유 이름 테이블쪽에서 feature를 생성하는 것은 불가능하기 때문이다. 양방향 연관관계가 설정되어 있다고 해서 featureName 객체에 feature를 삽입해봤자 JPA는 의도대로 동작하지 않는다.
다시 말하지만 양방향 연관관계를 설정하는 것은 양쪽에서 제어가 가능하게 하는 것이 아니다. 데이터베이스상에서는 연관관계의 주인쪽에서만 관계를 맺은 쪽의 데이터에 접근할 수 있으며, 반대쪽에서는 탐색의 역할만 가능하다.
'[ Backend ] > Spring DB, JPA' 카테고리의 다른 글
[Spring DB] 스프링과 트랜잭션, 트랜잭션 전파 (0) | 2023.07.02 |
---|---|
[JPA] 쓰기 지연으로 인한 서비스 오류 경험 (0) | 2023.06.21 |
[JPA] JDBC (0) | 2023.02.05 |
[QueryDsl] QueryDsl 사용해보기 (0) | 2022.11.22 |
[JPA] 순환참조, 무한참조 (0) | 2022.07.26 |