본문 바로가기
프로그래밍/JPA

[JPA] JPA 복합키 매핑 정리

by 노잼인간이라불립니다 2022. 8. 9.

 JPA 프로젝트를 하다가 복합키를 매핑해야하는 일이 생겼다. 근데 이 복합키는 간단한 2개의 필드에 선언하는 것이 아닌, 연관관계에 맞물려 있는 필드 였고, 이 문제를 해결하기 위해서 JPA 복합키에 대한 내용을 구글에 검색하던 중 어떤 사람은 @Id 와 @MapsId를 같이 사용하고, 어떤 사람은 각각 @Id 만을 사용하는 예제를 보았고, 어떤사람은 extends Serialize를 엔티티와 엔티티 id클래스에 모두 적용하는 사람이 있었고, entitiy Id 클래스에만 적용하는 사람이 있었다.

 

 그래서 복합키 매핑을 할 때 어떤 것이 맞는지, 또는 어떤 방법으로 해야하는지 혼란이 왔다. 그러다 어떠한 글을 보고 깨달음을 얻어 이렇게 정리한 내용을 남기려고한다.

 

일단 복합키를 선언하기 위한 조건들이 4가지가 있다.

 

/**
 * 참고 : 복합키의 4가지 조건
 *
 * @EmbeddedId(id클래스를 따로 만들어 객체로 만들어서 키로 선언할 때 사용) or @IdClass(각각의 필드 자체를 선언하여 복합키로 사용하고자 할때 클래스 위에 선언, 이 때 id클래스를 선언해주어야한다 ex @IdClass(xxxxId.class) 의 annotation.
 * no-args constructor의 접근 제한자는 public이어야 한다.
 * implements Serializable  (새로 만든 Id클래스에 선언해주어야 한다.)
 * equals() 와 hashCode() method를 override하거나 lombok을 이용해 선언 해 주어야한다. (Id Class도)
 */

 

그럼 정리를 시작해보겠다.

1. @Id, @Id 를 사용할 때에는 @EmbeddedId를 사용 하지 않을 경우에 사용한다.

   연관관계에 맞물려 있는 필드를 복합키로 사용할 경우에 이런 경우를 많이들 사용하는 것 같다. 만약 하나의 클래스로하여 복합키를 선언하게 된다면 나중에 객체 탐색을 하게 될 때 1depth 더 들어가야 하기 때문이라고 알고 있다.

 

2. @EmbeddedId를 사용할 경우에 연관관계에 있는 필드를 복합키로 선언하고자 한다면 @MapsId를 사용한다.

이때 Id클래스의 변수들의 타입은 연관관계 매핑을 한 객체의 pk 타입 or 일반 타입일 경우 동일한 타입으로 선언하고 @MapsId("xxxx") 에서 xxxx라고 적은 것을 변수명으로 한다.

 

ex)

 

@Entity
public class Member(){

    @MapsId("teamId")
    @ManyToOne
    @(JoinColumn(name = "team_id" )
    private Team team;

	@EmbeddedId
    private MemberId memberId;
}

public class MemberId implements Serializable{
	private Long teamId;
    
    private Long memberId;
}

3. 이 외에 @Id 만을 사용해서 복합키를 선언하고자 한다면 클래스위에 @IdClass(xxxxId.class)를 선언해주어야 한다.

 

ex)

@IdClass(MemberId.class)
public class Member {
	
    @Id
    @ManyToOne
    @JoinColumn(name="team_id")
    private Team team;
    
    @Id
    @Column(name = "member_id")
    private Long memberId;

}

public class MemberId implements Serializable {
	
    private Long team;
    
    private Long memberId; 
}