Everyday Dev System

JPA 복합키 설정하기 - @IdClass 본문

내배캠 주요 학습/JPA 심화

JPA 복합키 설정하기 - @IdClass

chaeyoung- 2023. 7. 31. 11:59

 

PK를 없애고 FK 두개로 복합키를 설정하는 방법이다.

2가지의 방식이 있는데, @IdClass로 하는 방법 먼저 소개하겠다.

 

@EmbaddedId로 하는 방법은 다음 글을 참조하면 된다.

2023.07.31 - [내배캠 주요 학습/JPA 심화] - JPA 복합키 설정하기 - @EmbeddedId

 

JPA 복합키 설정하기 - @EmbeddedId

복합키 위에 @EmbeddedId를 기재하여 사용하는 방법이다. > 1. @Embeddable 과 @EmbeddedId와 매핑 2. @MapsId("user_id") 와 @Column(name="user_id") 이 매핑이 되므로, 값이 동일 복합키 UserChannelId 클래스 코드 1. @Embedda

cdev.tistory.com

 

 

 

 

먼저 현재 상황은, User와 Channel의 다대다 관계로 인해 user_channel 이라는 중간 테이블이 도출되었다.

UserChannel 엔티티는 사용자와 채널을 연결하는 중간 테이블로, 여러 사요아가 여러 채널과 연관될 수 있도록 한다.

 

 

 

 

 

복합키 설정 클래스 코드

이때, UserChannelId 클래스를 새로 만들어 복합키를 설정해주면 된다. 

이 클래스는 UserChannel 엔티티의 주키를 나타내는 복합키로, UserChannel 테이블의 레코드를 식별하는데 사용한다.

 

1. implements Serializable → id로 설정하기 위해 반드시 필요하다.

  • Serializable 인터페이스는 자바에서 객체를 직렬화(Serialization)하여 데이터를 파일에 저장하거나 네트워크로 전송할 수 있게 해주는 인터페이스입니다.
  • 이 인터페이스를 구현함으로써, UserChannelId 클래스는 JPA 엔티티의 복합키로 사용할 수 있습니다.

 

 

2. private Long user  멤버 변수에 Entity 클래스에 필드명과 반드시 일치하도록 기재한다.

user, channel 두 속성이 UserChannel 엔티티의 주키 속성들과 대응된다. (엔티티 클래스에서 @Id 달려있는 속성들)

 

3. equals(), hashCode() 메서드 오버라이딩

클래스는 userchannel 속성을 기준으로 적절한 비교와 해싱을 위해 equalshashCode 메서드를 오버라이드 한다.

  • Object 클래스의 equals 메서드를 재정의하여, user와 channel 필드를 비교하여 두 객체가 같은지 확인합니다.
  • 객체의 자기 자신과 null을 비교하거나 다른 클래스의 객체와 비교하는 경우 예외 처리를 하여 안전성을 확보합니다.

 

 

package me.chaeyoung.jpa.userChannel;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Objects;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UserChannelId implements Serializable {
    // Serializable 는 id로 설정하기 위해 반드시 필요함.
    private Long user; // UserChannel 의 user 필드명과 동일 해야 함.
    private Long channel; // UserChannel 의 channel 필드명과 동일 해야 함.

    @Override
    public boolean equals(Object e){
        if (this == e) return true;
        if (e == null || getClass() != e.getClass()) return false;
        UserChannelId userChannelId = (UserChannelId) e;
        return Objects.equals(getUser(), userChannelId.getUser()) && Objects.equals(getChannel()
                , userChannelId.getChannel());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUser(), getChannel());
    }
}

 

 

 

 

UserChannel 클래스 코드

1. @IdClass(UserChannelId.class) → 복합키 설정하는 Entity 클래스 위에 기재

@IdClass(UserChannelId.class)는 복합키 클래스 UserChannelId가 이 엔티티의 식별자로 사용되는 것을 지정한다.

 

2. @Id  복합키로 설정한 멤버 변수 위에 기재

@Id 어노테이션은 userchannel 속성이 복합키의 일부임을 나타낸다.

 

package me.chaeyoung.jpa.userChannel;


import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import me.chaeyoung.jpa.channel.Channel;
import me.chaeyoung.jpa.user.User;

// lombok
@Getter
@NoArgsConstructor

// jpa
@Entity
@IdClass(UserChannelId.class)
public class UserChannel {

    @Builder
    public UserChannel(User user, Channel channel){
        this.user = user;
        this.channel = channel;
    }

    @Id
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @Id
    @ManyToOne
    @JoinColumn(name = "channel_id")
    private Channel channel;

}

 

 

요약하면, UserChannel 엔티티는 User와 Channel 사이의 다대다 관계를 나타내며,
UserChannelId 클래스는 중간 테이블에서 각 관계를 고유하게 식별하는 복합키를 나타낸다.
UserChannel 엔티티는 User와 Channel을 연결하는 역할을 하며,여러 사용자가 여러 채널과 연관되도록 해준다.