내가 처음 JPA를 접할 때, JoinColumn을 사용함에 있어 헷갈리는 부분이 있었다.
@JoinColumn 애노테이션에는, 다음과 같은 'name' 옵션이 존재한다.
나는 처음에 이 'name'옵션을 필수적인 옵션이고, value로는 매핑할 테이블의 칼럼 이름(FK, 외래키 이름)을 넣어줘야 작동하는줄 알고 있었다. 다음이 내가 잘못 이해한 예시다.
@Entity // Box 클래스
public class Box {
@Id @GeneratedValue
@Column(name = "BOX_ID")
private Long id;
private String name;
}
@Entity //Candy 클래스
public class Candy {
@Id @GeneratedValue
private Long id;
@Enumerated(EnumType.STRING)
private CandyType type;
@ManyToOne
@JoinColumn(name = "BOX_ID")
private Box box;
}
Candy가 N, Box가 1로 매핑되어있다.
Candy가 FK를 갖고있을테니, ManyToOne으로 매핑해준다.
이때 JoinColumn에 name은, Box에 존재하는 Column명으로 지정한다.
위와 같이 코드를 작성해도, 잘 작동한다. 그러나 내가 잘못 이해하고 있는 부분이 있었다.
@Entity
public class Box {
@Id @GeneratedValue
private Long id;
private String name;
}
위와 같이, Box 클래스에 있는 id의 이름을 지정해주지 않아도, JoinColumn은 잘 작동한다.
@JoinColumn(name = "BOX_ID")
분명 매핑할때, BOX_ID로 매핑을 했는데 이게 왜 작동하지? 싶어서 정보를 찾아보았다.
@JoinColumn(name = "BOX_ID")
@JoinColumn의 name은, 매핑할 테이블의 Column 이름중 하나를 찾아서 적는게 아니였다.
그냥, Candy 테이블에서 외래 키 필드의 이름을 BOX_ID로 지정해주는것이다.
@JoinColumn을 쓰는 순간, 매핑 대상 테이블의 PK를 가져와 FK로서 쓴다. 이때, 그냥 이 FK의 Column 이름을 지정해주는것이다. 매핑 대상 테이블 칼럼의 이름과는 아무 상관이 없다.
@JoinColumn의 name옵션은 선택이며, 이 name을 작성한다고 해서 매핑 대상 테이블 PK 이름을 name과 맞춰줄 필요는 없다.
매핑을 하다보면, 자기 자신과 매핑을 가질때가 있다.
마치 트리 자료구조처럼, 하나의 자료형(Table)을 가지고 트리처럼 구성하는 과정이다.
테이블 관점에서는, 그냥 본인 테이블의 PK를 FK로 갖는 필드가 하나 생기는것과 같다.
예시 코드는 다음과 같다.
@Entity
public class Tree {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "parent")
private Tree parent;
}
여기서도, @JoinColumn에 parent란 이름을 작성했다. 위와 마찬가지로, 이 parent라는 이름을 가진 Column을 찾는것이 아닌, 외래 키(FK) 필드 이름을 parent로 갖겠다는 의미다.