복합키 - @GeneratedValue 3

PPakSSam·2022년 1월 14일
0
post-thumbnail

복합키 목차

복합키 - @GeneratedValue 목차


@EmbeddedId 예제

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

복합키 - @GeneratedValue 시리즈는 위의 주장을 반박하기 위해서 쓴 포스트이다.
@IdClass를 사용하면 @GeneratedValue를 사용할 수 있음을 내 포스트에서 밝혔다.

그렇다면 @EmbeddedId를 사용해도 @GeneratedValue를 사용할 수 있을까?
결론을 말하자면 @EmbeddedId 경우 사용할 수 없다가 내 주장이다.
물론 항상 가능성을 열어두고자 한다. 나의 주장임을 알아주었음 한다.

실험한 코드는 다음과 같다.

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

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

    private String name;

    public Parent2(String name) {
        this.name = name;
    }
}

// 자식
@Entity
public class Child2 {

    @EmbeddedId
    private ChildId childId;

    private String name;

    @MapsId("parentId")
    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Parent2 parent;

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

        private Long parentId;

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

@GeneratedValue를 어디에 붙여야 할까?

첫번째

@Entity
public class Child2 {

    @EmbeddedId @GeneratedValue
    private ChildId childId;
    
    @Embeddable
    public static class ChildId implements Serializable {

        private Long parentId;

        @Column(name = "CHILD_ID")
        private Long id;
    }
}

맨 처음에 위의 방식대로 생각을 했었다.
그런데 위의 방식대로 하는 경우 childId에는 2개의 아이디가 있는데 어디에 아이디를 자동할당할 것인지 불분명해보였다.

두번째

@Entity
public class Child2 {

    @EmbeddedId 
    private ChildId childId;
    
    @Embeddable 
    public static class ChildId implements Serializable {

        private Long parentId;
		
        @GeneratedValue
        @Column(name = "CHILD_ID") 
        private Long id;
    }
}

parentId는 이미 Parnet2에서 자동할당 받았을 것이므로 그럼 나머지 부분인id만 자동할당받으면 될 것이므로 두번째 방식을 택하게 되었다.

다음과 같이 테스트코드를 작성하여 진행하였다.

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

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

    Child2.ChildId childId = new Child2.ChildId();
    childId.setParentId(saveParent.getId());

    Child2 child = Child2.builder()
            .name("자식")
            .parent(saveParent)
            .childId(childId)
            .build();
    childRepository.save(child);
}

그러니 다음과 같은 결과가 나왔다.

null값이 들어간걸로 보아 @GeneratedValue가 먹히지 않음을 알 수 있다.
따라서 @EmbeddedId의 경우 @GeneratedValue을 사용할 수 없음을 주장하게 되었다.

참고

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

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

0개의 댓글