개요
- 졸업프로젝트에서 사용자가 다른 사용자의 산책기록을 보고 좋아요를 클릭하는 과정이 필요하다.
- 좋아요 테이블을 생성하던 중 복합 기본키를 생성하는 것이 필요해짐.
- 좋아요 테이블의 경우 User의 PK와 산책 기록의 PK 두 컬럼으로 이루어져 있다.
- 평소같았으면, PK를 추가했겠지만, 식별관계로 만들면서 PK가 따로 존재하지 않는다.
- 이 과정을 JPA로 어떻게 매핑하는지 확인해보자
복합 기본키를 생성하는 방법 2가지
2가지 방법의 공통점
- 두 방법 모두 Serializable 인터페이스를 구현하여 키 클래스를 생성해야 한다.
- hashCode(), equals() 두개의 메소드가 오버라이딩해야 한다.
- 기본 생성자가 필요하다.
- public 접근제어자 설정이 필요하다.
@NoArgsConstructor
@EqualsAndHashCode
public class FavoriteId implements Serializable {
private Long user;
private Long walk;
}
1. @IdClass
- 관계형 데이터베이스에 더 가까운 방법이다.
- 복합 기본 키 필드를 별도의 클래스로 분리하여 매핑한다.
- 엔티티 관계 설정은 아래와 같이 해야 한다.
@Entity
@Getter
@IdClass(FavoriteId.class)
public class Favorite extends BaseEntity {
@Id
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@Id
@ManyToOne
@JoinColumn(name = "walk_id")
private Walk walk;
}
2. @EmbeddedId
- 객체지향에 가까운 방법이다.
- 복합 기본키를 엔티티 내부에 추가하여 정의한다.
- 마치, 복합 기본 키를 하나의 객체로 묶어 필드값에 Embedded하는 것과 같다.
@Entity
@Getter
public class Favorite extends BaseEntity {
@EmbeddedId
private FavoriteId favoriteId;
}
어떤 것을 써야 할까
- 기본적으로는 취향에 따라 사용하면 된다고 한다.
- 하지만 객체지향과, 데이터베이스의 관점을 나누어 생각해보자
1. @IdClass의 경우
Favorite favorite = new Favorite();
favorite.setUser(user);
favorite.setWalk(walk);
User user = favortie.getUser();
Walk walk = favortie.getWalk();
2. @EmbeddedId의 경우
Favorite favorite = new Favorite();
FavoriteId favoriteId = new FavoriteId(a,b);
favorite.setFavoriteId(favoriteId);
Long userId = favortie.getFavortieId().getUser();
Long walkId = favortie.getFavortieId().getWalk();
- Entity의 구조가 단순하고 기본 키 클래스가 Entity 내부에서만 사용되는 경우 @EmbeddedId
- 구조가 복잡하거나 복합 키의 재사용성이 높은 경우 @IdClass
김영한님 말씀을 인용해보자면
복합키 매핑은 저는 실무에서 거의 사용하지 않습니다. (두둥)
복합키 매핑에 대해서는 JPA책 7.3 복합 키와 식별 관계 매핑을 참고하시면 자세한 정보를 얻을 수 있을꺼에요.
그리고 아마 질문 주신 부분이 @IdClass, @EmbeddedId 둘중에 어떤 것을 선호하는가? 로 생각이 되는데요.
JPA책 @IdClass vs @EmbeddedId에서도 설명하지만 JPQL이 길어질 수 있어서 저는 개인적으로는 @IdClass를 조금 더 선호하는 편입니다.
@EmbeddedId: select p.id.id1, p.id.i2 from Parent p
@IdClass: select p.i1, p.id2 from Parent p
나만의 결론
- @IdClass 구현이 조금 더 직관적인 듯 하다.
- JPQL의 복잡도도 @IdClass가 더 좋다.
Reference
개요
- 졸업프로젝트에서 사용자가 다른 사용자의 산책기록을 보고 좋아요를 클릭하는 과정이 필요하다.
- 좋아요 테이블을 생성하던 중 복합 기본키를 생성하는 것이 필요해짐.
- 좋아요 테이블의 경우 User의 PK와 산책 기록의 PK 두 컬럼으로 이루어져 있다.
- 평소같았으면, PK를 추가했겠지만, 식별관계로 만들면서 PK가 따로 존재하지 않는다.
- 이 과정을 JPA로 어떻게 매핑하는지 확인해보자
복합 기본키를 생성하는 방법 2가지
2가지 방법의 공통점
- 두 방법 모두 Serializable 인터페이스를 구현하여 키 클래스를 생성해야 한다.
- hashCode(), equals() 두개의 메소드가 오버라이딩해야 한다.
- 기본 생성자가 필요하다.
- public 접근제어자 설정이 필요하다.
@NoArgsConstructor
@EqualsAndHashCode
public class FavoriteId implements Serializable {
private Long user;
private Long walk;
}
1. @IdClass
- 관계형 데이터베이스에 더 가까운 방법이다.
- 복합 기본 키 필드를 별도의 클래스로 분리하여 매핑한다.
- 엔티티 관계 설정은 아래와 같이 해야 한다.
@Entity
@Getter
@IdClass(FavoriteId.class)
public class Favorite extends BaseEntity {
@Id
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@Id
@ManyToOne
@JoinColumn(name = "walk_id")
private Walk walk;
}
2. @EmbeddedId
- 객체지향에 가까운 방법이다.
- 복합 기본키를 엔티티 내부에 추가하여 정의한다.
- 마치, 복합 기본 키를 하나의 객체로 묶어 필드값에 Embedded하는 것과 같다.
@Entity
@Getter
public class Favorite extends BaseEntity {
@EmbeddedId
private FavoriteId favoriteId;
}
어떤 것을 써야 할까
- 기본적으로는 취향에 따라 사용하면 된다고 한다.
- 하지만 객체지향과, 데이터베이스의 관점을 나누어 생각해보자
1. @IdClass의 경우
Favorite favorite = new Favorite();
favorite.setUser(user);
favorite.setWalk(walk);
User user = favortie.getUser();
Walk walk = favortie.getWalk();
2. @EmbeddedId의 경우
Favorite favorite = new Favorite();
FavoriteId favoriteId = new FavoriteId(a,b);
favorite.setFavoriteId(favoriteId);
Long userId = favortie.getFavortieId().getUser();
Long walkId = favortie.getFavortieId().getWalk();
- Entity의 구조가 단순하고 기본 키 클래스가 Entity 내부에서만 사용되는 경우 @EmbeddedId
- 구조가 복잡하거나 복합 키의 재사용성이 높은 경우 @IdClass
김영한님 말씀을 인용해보자면
복합키 매핑은 저는 실무에서 거의 사용하지 않습니다. (두둥)
복합키 매핑에 대해서는 JPA책 7.3 복합 키와 식별 관계 매핑을 참고하시면 자세한 정보를 얻을 수 있을꺼에요.
그리고 아마 질문 주신 부분이 @IdClass, @EmbeddedId 둘중에 어떤 것을 선호하는가? 로 생각이 되는데요.
JPA책 @IdClass vs @EmbeddedId에서도 설명하지만 JPQL이 길어질 수 있어서 저는 개인적으로는 @IdClass를 조금 더 선호하는 편입니다.
@EmbeddedId: select p.id.id1, p.id.i2 from Parent p
@IdClass: select p.i1, p.id2 from Parent p
나만의 결론
- @IdClass 구현이 조금 더 직관적인 듯 하다.
- JPQL의 복잡도도 @IdClass가 더 좋다.
Reference