본문 바로가기

프로그래밍언어/Java

org.hibernate.AnnotationException: referencedColumnNames(columnName) of ... referencing ... not mapped to a single property

org.hibernate.AnnotationException: referencedColumnNames(columnName) of A... referencing B... not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:180)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:88)
at org.hibernate.cfg.AnnotationConfiguration.processEndOfQueue(AnnotationConfiguration.java:456)
at org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:438)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:309)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1134)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1226)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:173)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:425)

Hibernate/JPA로 개발하는 도중 위의 에러가 발생하여 원인을 찾았는데 그 원인이 너무 사소한 실수로 인한 것이어서 포스팅을 한다.

일단 에러의 내용을 살펴보면 
  B...를 참조하는 A...의 참조컬럼이 단일속성으로 매핑되지 않는다. 
로 해석된다. 즉, 하나의 컬럼으로는 FK를 선언할 수 없다는 내용으로 이해하면 되며 결국 PK가 하나가 아니라는 말이된다.

위의 내용만을 본다면 @IdClass 나 @EmbeddedId 로 선언하여 단일키가 아닌 복합키로 PK를 선언했어야 했는데 아래와 같이 단일키로 생성했다. 

그런데 자세히 보면 이 도메인객체는 그 자체로 문제가 있다. 왜냐하면 @Id 선언이 두개가 되어 있기 때문이다.(붉은색 굵은 글씨 참고)
나중에 해결했을 땐 너무 어이없었지만 Copy&Paste 를 하는 과정에서 이런 실수를 할 수도 있을 것 같다. 아무쪼록 이글이 나와 같은 상황에서 빠른 문제해결이 될 수 있도록 도움이 되었으면 한다.

B:
@Entity
@Table(name = "TT_TROUBLE_TICKET")
public class TroubleTicket implements Serializable {

    /** UID */
    private static final long serialVersionUID = -6144092108662486502L;

    /** 장애아이디 */
    @Id
    @GeneratedValue(generator = "SQ_TT_TROUBLE_TICKET")
    @SequenceGenerator(name = "SQ_TT_TROUBLE_TICKET", initialValue = 1, allocationSize = 1, sequenceName = "SQ_TT_TROUBLE_TICKET")
    @Column(name = "TROUBLE_TICKET_ID", nullable = false)
    private long troubleTicketId;

    /** 샵아이디 */
    @Id // 제거해야함
    @Column(name = "SHOP_ID", length = 8)
    private String shopId;

}

A:
@Entity
@Table(name = "TT_COMMENT")
public class TroubleTicketComment implements Serializable {

    /** UID */
    private static final long serialVersionUID = 765699083453512999L;

    /** 조치내역아이디 */
    @Id
    @GeneratedValue(generator = "SQ_TT_COMMENT")
    @SequenceGenerator(name = "SQ_TT_COMMENT", initialValue = 1, allocationSize = 1, sequenceName = "SQ_TT_COMMENT")
    @Column(name = "COMMENT_ID", nullable = false)
    private long commentId;

    /** 장애 */
    @ManyToOne
    @JoinColumn(name = "TROUBLE_TICKET_ID", referencedColumnName = "TROUBLE_TICKET_ID", nullable = false)
    private TroubleTicket troubleTicket;
}