⭐알게 된 점⭐
👉 복합키 사용하기
- PK 없이 FK 2개를 사용하는 방법
- 선언 방법
1. @IdClass 활용
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserChannelId implements Serializable {
private Long user; // UserChannel 의 user 필드명과 동일해야함
private Long channel; // UserChannel 의 channel 필드명과 동일해야함
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserChannelId userChannelId = (UserChannelId) o;
return Objects.equals(getUser(), userChannelId.getUser()) && Objects.equals(getChannel(), userChannelId.getChannel());
}
@Override
public int hashCode() {
return Objects.hash(getUser(), getChannel());
}
}
---------------------------------------------------------------------------------------
@Entity
@IdClass(UserChannelId.class)
public class UserChannel {
....
@Id
@ManyToOne
@JoinColumn(name = "user_id")
User user;
@Id
@ManyToOne
@JoinColumn(name = "channel_id")
Channel channel;
...
}
2. @EmbeddeId 활용
@Entity
public class UserChannel {
@EmbeddedId
private UserChannelId userChannelId;
...
@ManyToOne
@MapsId("user_id")
User user;
@ManyToOne
@MapsId("channel_id")
Channel channel;
...
}
-------------------------------------------------------------------------------
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Embeddable
public class UserChannelId implements Serializable {
@Column(name = "user_id")
private Long userId;
@Column(name = "channel_id")
private Long channelId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserChannelId userChannelId = (UserChannelId) o;
return Objects.equals(getUser(), userChannelId.getUser()) && Objects.equals(getChannel(), userChannelId.getChannel());
}
@Override
public int hashCode() {
return Objects.hash(getUser(), getChannel());
}
}
👉 영속성 전이(Cascade) + 고아 객체 제거(orphanRemoval)
Cascade
- @OneToMany 혹은 @OneToOne에서 사용
- 양쪽 엔티티의 라이프 사이클이 동일하거나 비슷해야함
- 대상 엔티티로의 영속성 전이는 현재 엔티티에서만 전이 되어야 함
orphanRemoval
- @OneToMany 혹은 @OneToOne에서 사용
- Cascade.REMOVE와 비슷한 용도로 쓰임
- 부모 객체에서 리스트 요소 삭제 했을 경우 해당 자식 객체는 매핑 정보가 없어지므로 대신 삭제
영속성 전이 최강 조합 : orphanRemoval=true + Cascade.ALL
-> 두개를 함께 설정하면 자식 엔티티의 라이프 사이클이 부모 엔티티와 동일해지며, 직접 자식 엔티티의 생명주기를 관리할 수 있게 되므로 자식 엔티티의 Repository가 필요가 없어짐
👉 QueryDSL
- QueryDSL의 Predict 인터페이스로 조건문을 여러개 구성하여 따로 관리할 수 있음
- findOne(Predict), findAll(Predict) 이 메서드가 주로 사용됨
- Join이 필요한 쿼리일 경우 사용할 수 없음
🐰 END
JPA 심화 강의를 수강하는데 계획했던 것보다 시간이 좀 더 필요할 것 같다!