복합키 - 식별 관계에서 위의 다이어그램을 예제로 진행했었다. 여기서는 각각의 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);
}
테스트 결과 아래의 사진처럼 나왔고 성공했음을 알 수 있다.
복합키에서는
@GeneratedValue
를 통해 기본키를 자동생성할 수 없다
구글링했을 때 위의 정보를 많이 찾을 수 있었다. 하지만 실험결과 가능함을 증명했다.
이를 통해 얻을 수 있는 교훈은 항상 정보를 받아들일 때 비판적으로 받아들이자는 것과 항상 배우는 태도로 실험을 해보자는 것이다. 좋은 교훈이 되었다.
포스팅의 전체적인 코드는 깃헙코드에서 볼 수 있다.