JPA에서 연관관계 설정과 @JoinColumn 어노테이션에 대해 다뤄보겠습니다.
우리는 테이블 간의 연관관계를 설정할 때 주로 일대다(1:N) 또는 다대일(N:1) 관계를 많이 사용하게 됩니다. 이때 연관관계를 설정하는 과정에서 @JoinColumn 어노테이션을 사용하게 되는데, 저 역시 이 어노테이션의 역할을 처음에는 오해하고 있었습니다.
@JoinColumn의 진짜 역할은?@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
위 코드에서 @JoinColumn 어노테이션은 외래 키 컬럼의 이름을 설정하는 역할을 합니다. 저는 처음에 이 어노테이션이 외래 키로 연결되는 대상 테이블의 컬럼명을 지정한다고 생각했었죠. 예를 들어, Member 엔티티의 id 필드가 member_id로 정의되어 있으니, Order 테이블에 외래 키도 member_id라고 정의해줘야 하는 줄 알았습니다.
하지만, 그건 잘못된 생각이었습니다. 사실 @JoinColumn의 name 속성은 외래 키가 정의될 테이블(Order 테이블)에 사용될 컬럼명을 지정하는 것입니다. 즉, 연관관계의 주인 테이블에 생성되는 외래 키 컬럼의 이름을 정하는 역할입니다.
referencedColumnName그렇다면 어떻게 Order 테이블이 Member 테이블의 특정 컬럼과 연결된다는 것을 알 수 있을까요?
여기서 등장하는 것이 바로 referencedColumnName 속성입니다.
@JoinColumn의 referencedColumnName 속성은 외래 키가 참조하는 대상 테이블의 컬럼 이름을 지정합니다. 즉, Order 테이블의 외래 키가 Member 테이블의 어떤 컬럼과 매핑되는지를 알려주는 속성입니다.
하지만 이 속성은 생략이 가능합니다. 왜냐하면 JPA는 기본적으로 대상 테이블의 기본 키(PK)를 자동으로 참조하게 되어 있기 때문입니다. 그래서 referencedColumnName 속성을 생략하면 자동으로 참조되는 컬럼이 대상 테이블의 기본 키로 설정됩니다.
Member와 OrderMember 엔티티@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
@NotEmpty
private String name;
@Embedded
private Address address;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
Order 엔티티@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {
@Id @GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id") // 외래 키 컬럼 이름 설정
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "delivery_id")
private Delivery delivery;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
}
위 코드에서, @JoinColumn(name = "member_id")는 Order 테이블에 외래 키 컬럼을 member_id라는 이름으로 생성하는 역할을 합니다. 이때 referencedColumnName을 따로 지정하지 않으면, JPA는 자동으로 Member 테이블의 기본 키(PK)를 참조합니다. 즉, member_id 컬럼은 자동으로 Member 엔티티의 id 필드와 매핑됩니다.
@JoinColumn은 외래 키 컬럼의 이름을 설정하는 어노테이션입니다.name 속성은 현재 테이블에 생성될 외래 키 컬럼의 이름을 지정합니다.referencedColumnName 속성은 참조할 대상 테이블의 컬럼을 지정합니다. 생략하면 기본적으로 대상 테이블의 기본 키를 참조합니다.앞으로 @JoinColumn을 사용할 때 더 이상 혼동하지 않고 정확하게 사용할 수 있겠죠? 😊