기본적인 연관관계 맵핑
우리가 보통 JPA를 이용해 연관관계를 맵핑할 때는 @ManyToOne
(다대일 관계인 경우)과 @JoinColumn
어노테이션을 사용한다.
예를 들어, User
테이블과 Product
테이블이 있다고 가정하자.
그리고 다른 제3의 테이블에서 두 테이블(User, Product) 모두와 다대일 관계를 맺는 경우 다음과 같이 작성할 수 있다.
@ManyToOne을 통해 해당 테이블과 다대일 관계임을,
@JoinColumn을 통해 해당 테이블에서 특정 테이블의 pk를 외래키로 가짐을 선언할 수 있다.
결과적으로 발생하는 DDL은 아래와 같다.
참조한 테이블의 컬럼으로 user_id와 product_id가 포함되었으며,
외래키로 두 필드가 설정되었음을 확인할 수 있다.
여기서 주의해야할 점은 @JoinColumn
의 name
속성에 단순히 참조하는 키의 컬럼명을 써주는게 아니라는 사실이다
두개 이상의 컬럼이 한 테이블을 참조하는 경우
다음과 같은 경우를 보자.
한 테이블 내에서 User
테이블을 2개의 컬럼이, Product
테이블을 2개의 컬럼이 참조한다.
이 경우 위와 같이 @JoinColumn
어노테이션을 설정한 후 돌려보면 아래와 같은 오류가 발생한다.... Repeated column in mapping for entity
라는 부분을 통해 같은 컬럼을 두 번 맵핑했다는 의미임을 예측할 수 있다..
해결법
이를 해결하기 위해서는 @JoinColumn
어노테이션의 속성이 정확히 무엇을 의미하는지 알아야 한다.
- name
: 맵핑할 외래키의 이름
- referencedColumnName
: 외래키가 참조하는 대상 태이블의 pk 이름
즉, 위의 product_id와 user_id 와 같은 실제 pk명은 name
속성이 아니라 referencedColumnName
속성에 적어주어야 한다.
따라서, 다음과 같이 수정 후 서버를 다시 돌려보자.
# 생성된 create 문
create table exchange (
exchange_id bigint not null auto_increment,
acceptor_confirm_yn bit not null,
exchange_complete_dt datetime(6),
exchange_complete_yn bit not null,
requester_confirm_yn bit not null,
# 아래 4줄 주목!!
acceptor_id bigint not null,
acceptor_product_id bigint not null,
requester_id bigint not null,
requester_product_id bigint not null,
primary key (exchange_id))
위와 같이 우리가 name 속성에 설정한 이름으로 컬럼명이 설정되어 DDL이 생성된 것을 확인할 수 있다.