Spring JPA 또는 Domain Object를  REST로 서비스를 할 때 클라이언트쪽으로 전달시 JSON으로 변환을 하게 됩니다. JPA의 경우 복합키를 표현하는 경우 다음과 같이 @Embeddable annotation을 써서 표현할 수 있습니다. 

@Getter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Embeddable
@NoArgsConstructor
public class PayId implements Serializable {

    /**
     * 결제번호 (비즈니스적으로 유의미한 번호)
     */
    @EqualsAndHashCode.Include
    @Column
    private Long payNumber;

    @EqualsAndHashCode.Include
    @Column
    private Long paySeq;

    public PayId(Long payNumber, Long paySeq) {
        this.payNumber = payNumber;
        this.paySeq = paySeq;
    }
}

그러나 이렇게 사용하는 경우 다음과 같이 Entity에 PK로 정의를 해야 하며 이 경우 JSON으로 변환하면 계층 구조를 갖도록 생성이 됩니다.

@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Entity
@NoArgsConstructor
public class PayDetailId implements Serializable {

    @EqualsAndHashCode.Include
    private PayId payId;

    @EqualsAndHashCode.Include
    @Column
    private Long payDetailId;

    public PayDetailId(PayId payId, Long payDetailId) {
        this.payId = payId;
        this.payDetailId = payDetailId;
    }
}

예를 들면 이렇게 변환이 됩니다. 만약 payNumber를 payId 아래에 두지 않고 payId 와 같은 레벨에 두고자 한다면 @JsonUnwrapped annotation이 제격입니다.

{
    "payId" : 
    {
        "payNumber": 100,
        "paySeq" : 5000
    },
    "payDetailId": 1
}

다음과 같이 펼쳐서 전송하고자 하는 경우 다음과 같이 @JsonUnwrapped annotation을 추가합니다.

@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Entity
@NoArgsConstructor
public class PayDetailId implements Serializable {

    @EqualsAndHashCode.Include
    @JsonUnwrapped
    private PayId payId;

    @EqualsAndHashCode.Include
    @Column
    private Long payDetailId;

    public PayDetailId(PayId payId, Long payDetailId) {
        this.payId = payId;
        this.payDetailId = payDetailId;
    }
}

그러면 아래와 같이 자동 생성됩니다.

{
    "payNumber": 100,
    "paySeq": 5000,
    "payDetailId": 1
}

1 Comment

  1. Edward AUTHOR

    JPA Entity Mapping에 대한 보다 재미난 글은 https://woowabros.github.io/experience/2019/01/04/composit-key-jpa.html을 참고하십시오.