오류 내용
Repeated column in mapping for entity: message.Message column: member_id (should be mapped with insert="false" update="false")
엔티티 매핑을 하는데 반복되는 컬럼이 있다고 한다. 현재는 메세지 테이블의 송,수신자 필드가 모두 member_id를 참조하고 있다.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member sender;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member receiver;
해결 과정
@JoinColumn
어노테이션의 속성은 다음과 같다.
그렇다면 referencedColumnName에 member_id를 pk로 가리키고 name으로 송,수신자의 id를 사용하면 되지 않을까 라는 생각으로 코드를 수정하였다.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(referencedColumnName = "member_id", name = "sender_id", nullable = false)
private Member sender;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(referencedColumnName = "member_id", name = "receiver_id", nullable = false)
private Member receiver;
Unable to find column with logical name: member_id in org.hibernate.mapping.Table(member) and its related supertables and secondary tables
번역기를 돌려보니 table 및 관련 슈퍼 테이블, 보조 테이블에서 member_id의 이름을 가지는 컬럼을 찾을 수 없다고 한다.
이 오류를 해결할 방법을 찾지 못해 계속 고민하고 있었는데, 구글링을 하는 도중 김영한님의 답변을 보았다.
referencedColumnName을 생략하면 대상 테이블의 PK로 자동 지정된다고 한다. 그래서 PK가 아닌 다른 컬럼에 직접 지정할 수도 있지만 정규화 관점에서는 권장하지 않는다고 한다.
그래서 referencedColumnName을 생략하니 정상적으로 작동하게 되었다.
정리
referencedColumnName은 생략하면 대상 테이블의 PK로 자동 지정이 된다.
하나의 엔티티에서 두 개의 같은 엔티티를 매핑할 때에는 name에 외래키의 이름을 설정해주어야 한다.
이해하지 못한 것 (해결 완료)
referencedColumnName를 생략하면 member의 member_id를 기본키로 가리키는 것으로 이해했는데 생략하지 않고 member_id를 가리키도록 명시하면 왜 오류가 발생할까?
-> referencedColumnName를 생략하는 경우의 기본키는 다른 것을 가리킨다?
-> 해결
@Entity
@Getter
public class Member extends Timestamped {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long memberId;
@Column(nullable = false, length = 45, unique = true)
private String email;
@Column(nullable = false, length = 100)
private String password;
@Column(nullable = false, length = 45, unique = true)
private String username;
// ...
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(referencedColumnName = "memberId", name = "sender_id", nullable = false)
private Member sender;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(referencedColumnName = "memberId", name = "receiver_id", nullable = false)
private Member receiver;
referencedColumnName의 값으로 member_id가 아닌 memberId를 넣어주니 정상적으로 작동하였다. 아무래도 referencedColumnName가 가리키는 PK는 데이터베이스 컬럼 이름이 아니라 엔티티 클래스에 있는 Id가 가리키는 필드 명을 기본값으로 넣어주는 것 같다.