결론: @JoinColumn(referencedColumnName = [참조하는 필드 이름])
공부 겸 진행중인 스프링 부트 프로젝트에서 생긴 문제이다. Solved
라는 table에서 School
의 필드를 참조하는 FK를 가져야 하는 상황이다. 각 Entity 코드는 다음과 같다.
@Entity
public class School implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="school_id", nullable = false, unique = true)
private Long schoolId; // 학교 번호
@OneToMany(mappedBy = "school")
private Set<Solved> solvedSet = new HashSet<>();
...
}
@Entity
public class Solved {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "school_id")
private School school;
...
}
처음에 생각으로는 @JoinColumn(name = "school_id")
라고 입력했으니까 당연히 Hibernate가 school_id
를 참조하지 않을까 생각했다. 책과 인터넷에 나오는 예제도 다 이런 식으로만 작성되어 있었고...
그런데 아니었다. Hibernate에서는 자꾸 school_id
column이 아닌 id
column을 참조하는 table을 만들었다. 테스트를 돌리면 table을 생성하는 과정에서 다음과 같은 쿼리를 확인할 수 있었다.
Hibernate: alter table solved add constraint FK3d1skgq7xw652uvo5mi5sbd26 foreign key (school_id) references school (id)
결국 문제는 'Hibernate에게 어떻게 school_id
를 참조하도록 강제하는가'였는데, 답은 간단했다. @JoinColumn
에 referencedColumnName
의 값으로 참조하길 원하는 필드 이름만 넣어주면 되는 것이다. 즉, Solved
의 코드를 다음과 같이 수정하면 된다.
@Entity
public class Solved {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "school_id", referencedColumnName = "school_id")
private School school;
...
}
테스트를 돌려봤더니 아주 잘 작동한다.
Hibernate: alter table solved add constraint FK3d1skgq7xw652uvo5mi5sbd26 foreign key (school_id) references school (school_id)
공식문서를 찾아보니 referencedColumnName
의 기본값은 Primary Key라고 한다.
Default (only applies if single join column is being used): The same name as the primary key column of the referenced table.
내가 따로 값을 설정해주지 않아서 자동으로 PK를 참조하게 된 것이다. PK외에 다른 필드를 참조해야할 경우에는 반드시! 필드 이름을 넘겨줘야겠다.
여기서 주의해야할 점이 한 가지 있는데, Hibernate의 오류(?)인지 이 경우 School
이 Serializable
을 implements해야 에러 없이 잘 작동한다. Hibernate 프로젝트에 이슈로 올라와있다.
JPA JoinColumns 사용시 주의 사항 - Yoo Young-mo님
안녕하세요, 글 잘봤습니다!
PK인 FK를 만들때, 해당 relation table에서는 FK가 nullable 이 가능한데,
FK 제약조건 오류가 납니다. 이런 경우는 왜 그런지 아시나요?
아래와 같은 구조일 때요..
Child {
@ManyToOne
@JoinColumn(name="parent_id", nullable = true)
private Parent parent;
}