쌩로그
JPA Entity에서 참조를 맺는 @JoinColumn 애너테이션에 대한 오개념 정리(조금 더 정확히는 name 속성에 관하여) 본문
JPA Entity에서 참조를 맺는 @JoinColumn 애너테이션에 대한 오개념 정리(조금 더 정확히는 name 속성에 관하여)
.쌩수. 2024. 4. 3. 00:48목록
- 포스팅 개요
- 본론
2-1. 문제 인식 배경
 2-2. 문제 발생의 원인
2-3. 문제 발생을 일으키게 된 이유 - 요약
1. 포스팅 개요
해당 포스팅은 제목과 같이 JPA Entity에서 외래 키와 참조를 맺는 @JoinColumn 애너테이션에 대한 오개념
을 바로잡기 위한 포스팅이다.
2. 본론
2-1. 문제 인식 배경
현재 회사에서 진행 중인 프로젝트는 여러 사용자가 하나의 데이터에 접근해서 수정할 수도 있고, 삭제할 수도 있다.
즉, A 사용자가 생성하고 B 사용자가 수정했다가 C 사용자가 삭제할 수도 있는 구조다.
(사내 서비스라 요구사항이 이렇다.)
따라서 학습차원에서 했던 프로젝트처럼 어떤 게시물에 대해서 작성자만 접근할 수 있는 구조가 아니라서 생성날짜 및 수정날짜보단 누가 데이터를 생성했고, 수정했는지가 더 중요하다.
그래서 이에 맞게 유지보수를 하던 중 생성자와 수정자가 Member를 참조하는 외래키로 하는 것이 좋을 것 같다는 피드백을 얻었고,
그에 따라 어떤 사용자의 요청에 의해 생성되는 데이터 DB에서 매핑되는 테이블에서 생성자와 수정자의 의미를 지니는 외래 키를 두기 위해서 Member의 기본 키에 두 번을 참조하게 했다.
게시판을 예로 든 코드인데, 다음과 같다.
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id)
private Long id;
@ManyToOne
@JoinColumn(name = "member_id)
private Member creator;
@ManyToOne
@JoinColumn(name = "member_id)
private Member modifier;
}
위와 같은 식으로 Entity를 설계했다.
그리고 서버를 실행했을 때 오류가 났다.
2-2. 문제 발생의 원인
원인은 간단했다.
참조를 맺으려는 컬럼이 중복된 컬럼 이기때문에 오류가 발생했던 것이었다.
2-3. 문제 발생을 일으키게 된 이유
제목과 같이 @JoinColumn
의 name 속성에 대해 잘 못 알고 있었다.
위와 같은 엔티티를 테이블로 옮겨보자면 다음과 같다.
key 여부 | column |
---|---|
PK | board_id |
... | ... |
FK | member_id |
FK | member_id |
그렇지만 내가 원했던 테이블은 다음과 같다.
key 여부 | column |
---|---|
PK | board_id |
... | ... |
FK | creator |
FK | modifier |
이 때까지 @JoinColumn
의 name에는 참조하는 엔티티의 Id 필드(테이블로는 PK 컬럼명)를 넣는 것인 줄 알았는데,
Entity에서 그냥 필드로 다음과 같이 참조를 하면, DB의 테이블에서는 해당 Entity(테이블)의 id를 바라보도록 되어있던 것이었다.
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id)
private Long id;
@Column(name = "member_id)
private Member member;
}
이런 식으로 말이다.
그렇기 때문에 @joinColumn
의 name 속성의 값으로는 참조하는 테이블의 PK 명을 넣는 것이 아니라,
(게시판을 예로 들면) 게시판에서 Member의 id를 참조하는 외래 키의 이름을 지정하면 된다.
다시 말해서 Member의 id를 생성자와 수정자를 위해 두 번을 참조하면서, FK의 컬럼명을 creator
, modifier
로 주고 싶을 때 다음과 같이 하면 된다.
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "board_id)
private Long id;
@ManyToOne
@JoinColumn(name = "creator")
private Member creator;
@ManyToOne
@JoinColumn(name = "modifier")
private Member modifier;
}
그러면 creator 와 modifier 의 필드가 Board 테이블에서 Member를 참조하는 FK의 컬럼명이 creator
와 modifier
로 매핑된다.
그럼 다음과 같이 내가 원하는 결과가 나온다.
key 여부 | column |
---|---|
PK | board_id |
... | ... |
FK | creator |
FK | modifier |
3. 요약
결론은 @JoinColumn
에서의 name 속성 값은 참조하려는 테이블의 PK 컬럼 명을 넣는 것이 아니라,
참조를 하는 외래 키(FK)의 컬럼명을 지정하는 것이다!!
'Spring > JPA' 카테고리의 다른 글
실전! Queydsl (feat. JPA 로드맵의 끝 + 앞으로의 계획살짝) (2) | 2024.03.03 |
---|---|
자바 ORM 표준 JPA 프로그래밍 Ch.16. 트랜잭션과 락, 2차 캐시 (0) | 2024.02.27 |
자바 ORM 표준 JPA 프로그래밍 Ch.14. 컬렉션과 부가 기능 (2) (0) | 2024.02.23 |
자바 ORM 표준 JPA 프로그래밍 Ch.12. 스프링 데이터 JPA (0) | 2024.02.21 |
실전! 스프링 데이터 JPA (인프런 - 김영한) (0) | 2024.02.18 |