복합키 - @GeneratedValue 1

PPakSSam·2022년 1월 13일
1
post-thumbnail

복합키 목차

복합키 - @GeneratedValue 목차


식별 관계 @IdClass 예제

복합키 - 식별 관계에서 위의 다이어그램을 예제로 진행했었다. 여기서는 각각의 Id가 String이었고 직접 Id값을 할당하는 구조였다.

문득 이런생각이 들었다.
Id를 직접할당하는 것 말고 @GeneratedValue를 이용하여 DB에 위임하는 방법은 없을까?
그래서 직접 실험해보도록 했다.

// 부모
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Parent {

    @SequenceGenerator(
            name = "parent_id_seq",
            sequenceName = "parent_id_seq",
            allocationSize = 1
    )
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "parent_id_seq")
    @Column(name = "PARENT_ID")
    private Long id;

    private String name;
}

// 자식
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@IdClass(Child.ChildId.class)
public class Child {

    @SequenceGenerator(
            name = "child_id_seq",
            sequenceName = "child_id_seq",
            allocationSize = 1
    )
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "child_id_seq")
    @Column(name = "CHILD_ID")
    private Long id;

    @Id
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;

    private String name;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ChildId implements Serializable {

        private Long id;
        private Long parent;
    }
}

// 손자
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@IdClass(GrandChild.GrandChildId.class)
@Entity
public class GrandChild {

    @SequenceGenerator(
            name = "grandchild_id_seq",
            sequenceName = "grandchild_id_seq",
            allocationSize = 1
    )
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "grandchild_id_seq")
    @Column(name = "GRANDCHILD_ID")
    private Long id;

    @Id
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID"),
        @JoinColumn(name = "CHILD_ID", referencedColumnName = "CHILD_ID")
    })
    private Child child;

    private String name;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class GrandChildId implements Serializable {

        private Long id;
        private Child.ChildId child;
    }
}

  • @SequenceGenerator를 이용하였다.

    • 그냥 @GeneratedValue만 이용하면 부모,자식,손자 모두 같은 시퀀스를 공유한다.
    • 부모, 자식, 손자 각각 다른 시퀀스에서 아이디를 할당받는 것이 합리적이다.

  • 식별자 클래스를 내부클래스로 등록했다.

    • 어차피 식별자 클래스는 해당 엔티티만 사용하므로 굳이 외부클래스로 두어 공간을 낭비하지 않도록 설계했다. -> 개인적인 의견이다!

위의 코드처럼 설계를 한 후 다음과 같이 테스트 코드를 작성해봤다.

@Test
@DisplayName("insert Test")
public void insertTest() throws Exception {

    Parent parent = new Parent("부모");
    Parent saveParent = parentRepository.save(parent);

    Child child = Child.builder()
            .name("자식")
            .parent(saveParent)
            .build();
    Child saveChild = childRepository.save(child);

    GrandChild grandChild = GrandChild.builder()
            .name("손자")
            .child(saveChild)
            .build();
    grandChildRepository.save(grandChild);
}

테스트 결과 아래의 사진처럼 나왔고 성공했음을 알 수 있다.



참고1

복합키에서는 @GeneratedValue를 통해 기본키를 자동생성할 수 없다

구글링했을 때 위의 정보를 많이 찾을 수 있었다. 하지만 실험결과 가능함을 증명했다.
이를 통해 얻을 수 있는 교훈은 항상 정보를 받아들일 때 비판적으로 받아들이자는 것과 항상 배우는 태도로 실험을 해보자는 것이다. 좋은 교훈이 되었다.

참고2

포스팅의 전체적인 코드는 깃헙코드에서 볼 수 있다.

profile
성장에 대한 경험을 공유하고픈 자발적 경험주의자

0개의 댓글