복합키란 기본키 없이 외래키가 2개 존재하는 것을 의미한다. 이를 선언하는 2가지 방법이 있다.
복합키를 사용할 엔티티 위에 @IdClass
애너테이션을 붙인다. 2개의 외래키에 @Id
애너테이션을 붙여주면 간단히 사용할 수 있다.
@Entity
@IdClass(UserChannelId.class)
public class UserChannel {
@Id
@ManyToOne
@JoinColumn(name = "user_id")
User user;
@Id
@ManyToOne
@JoinColumn(name = "channel_id")
Channel channel;
}
@EmbeddedId
애너테이션은 복합키 클래스를 따로 생성하여 사용해준다. UserChannel 클래스에 복합키를 선언하기 위해 UserChannelId 클래스를 우선 만들어준 뒤, @Embeddable
애너테이션을 붙여준다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Embeddable
public class UserChannelId implements Serializable {
@Column(name = "user_id")
private Long userId;
@Column(name = "channel_id")
private Long channelId;
// equals, hashCode 메서드 등을 구현할 수 있다.
}
이후 UserChannel 클래스에 UserChannelId 복합키를 @EmbeddedId
애너테이션을 통해 선언한다. 또한 user와 channel 외래키에 @JoinColumn
애너테이션 대신 @MapId
애너테이션을 사용한다.
cascade 옵션을 사용하면 영속성 전이가 가능하다. 연관관계의 주인이 아닌 부모 엔티티에서 사용하며 부모 객체가 삭제될때 자식 객체도 삭제되도록 하는 등의 상태 전이가 가능하다.
옵션 종류
- ALL : 전체 상태 전이
- PERSIST : 저장 상태 전이
- REMOVE : 삭제 상태 전이
- MERGE : 업데이트 상태 전이
- REFERESH : 갱신 상태 전이
- DETACH : 비영속성 상태 전이
orphanRemoval은 Cascade.REMOVE와 비슷하게 삭제를 전파하는데 쓰이며 고아 객체를 제거한다. 다만 cascade와의 차이점은 orphanRemoval=true는 리스트 요소로써의 영속성 전이도 가능하다는 것이다. 부모 리스트에서 요소를 삭제하면 자식 엔티티까지 삭제된다.
⚠️ orphanRemoval=true + Cascade.ALL
을 같이 설정하면 자식 엔티티의 라이프 사이클이 부모 엔티티와 동일해지며 직접 자식 엔티티의 생명주기를 관리할 수 있게 되므로 자식 엔티티의 리포지토리조차 없어도 된다.