[Spring]N:N 관계와 복합키, @EmbeddedId

JUNYOUNG·2024년 6월 10일

복합키 사용 (N:N 관계에서 @EmbeddedId 사용)

1. 데이터베이스 테이블 예시

데이터베이스에는 두 개의 테이블인 UserChallenge가 있고, 이 두 테이블은 N:N 관계를 가지고 있다고 가정

2. 테이블 구조

CREATE TABLE user (
    user_id BIGINT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);

CREATE TABLE challenge (
    challenge_id BIGINT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT
);

CREATE TABLE challenge_user (
    challenge_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    PRIMARY KEY (challenge_id, user_id),
    FOREIGN KEY (challenge_id) REFERENCES challenge (challenge_id),
    FOREIGN KEY (user_id) REFERENCES user (user_id)
);

3. @EmbeddedId 사용하여 복합키 구현

3-1. 복합키 클래스 정의

먼저 복합키를 정의하기 위해 ChallengeUserId 클래스를 작성합니다.

import jakarta.persistence.Embeddable;
import java.io.Serializable;
import java.util.Objects;

@Embeddable
public class ChallengeUserId implements Serializable {
    private Long challengeId;
    private Long userId;

    // 기본 생성자
    public ChallengeUserId() {}

    // 매개변수 있는 생성자
    public ChallengeUserId(Long challengeId, Long userId) {
        this.challengeId = challengeId;
        this.userId = userId;
    }

    // Getters and Setters
    public Long getChallengeId() {
        return challengeId;
    }

    public void setChallengeId(Long challengeId) {
        this.challengeId = challengeId;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    // equals()와 hashCode() 반드시 구현
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ChallengeUserId that = (ChallengeUserId) o;
        return Objects.equals(challengeId, that.challengeId) && Objects.equals(userId, that.userId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(challengeId, userId);
    }
}
3-2 앤터티 클래스 정의
import jakarta.persistence.*;
import java.util.Date;

@Entity
@Table(name = "challenge_user")
public class ChallengeUser {

    @EmbeddedId
    private ChallengeUserId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("challengeId")
    @JoinColumn(name = "challenge_id")
    private Challenge challenge;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("userId")
    @JoinColumn(name = "user_id")
    private User user;

    private Date joinedAt;

    // 기본 생성자
    public ChallengeUser() {}

    // 매개변수 있는 생성자
    public ChallengeUser(ChallengeUserId id, Challenge challenge, User user, Date joinedAt) {
        this.id = id;
        this.challenge = challenge;
        this.user = user;
        this.joinedAt = joinedAt;
    }

}

4. 관계 매핑

  • User 엔터티에서 다대다 관계를 매핑합니다.
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;

    private String username;
    private String email;

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ChallengeUser> challengeUsers = new HashSet<>();

}
  • Challenge 엔터티에서 다대다 관계를 매핑합니다.
@Entity
@Table(name = "challenge")
public class Challenge {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long challengeId;

    private String name;
    private String description;

    @OneToMany(mappedBy = "challenge", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ChallengeUser> challengeUsers = new HashSet<>();

    // Getters and Setters
}

5. 복합키 설명

1. 고유성 보장
  • 중복 데이터 방지: 여러 열의 조합으로 고유 키를 생성하여 데이터의 중복 삽입을 방지.
  • 자연스러운 키: 비즈니스 로직에 맞는 자연스러운 고유 키를 생성 가능.
2. 효율적인 관계 표현
  • 참조 무결성 유지: 테이블 간의 관계를 명확하게 정의하고 외래 키로 참조 무결성을 보장.
  • 성능 최적화: 인덱스를 효과적으로 사용하여 데이터 검색과 조인 성능을 향상.
3. 다대다 관계 관리
  • N:N 관계 표현: 교차 테이블을 사용하여 다대다 관계를 효율적으로 관리.
  • 유연한 모델링: 복잡한 다대다 관계를 직관적으로 표현 가능.
4. 데이터 무결성 강화
  • 일관성 유지: 복합키로 데이터의 일관성을 높이고, 비즈니스 규칙을 적용하여 데이터 무결성 보장.
  • 제약 조건 적용: 데이터베이스 레벨에서 비즈니스 규칙을 강제하여 추가 검증 필요성 감소.
5. 성능 및 확장성
  • 빠른 데이터 조회: 복합키를 통해 인덱싱 성능을 향상시켜 대규모 데이터에서의 조회 속도 개선.
  • 확장성 제공: 대규모 데이터베이스에서 효율적인 관리와 확장성 확보.
6. 비즈니스 로직 반영
  • 비즈니스 규칙 구현: 복합키로 비즈니스 로직을 직접 데이터베이스 구조에 반영.
  • 데이터 무결성 유지: 데이터베이스 차원에서 비즈니스 로직을 적용하여 무결성 강화.
profile
Onward, Always Upward - 기록은 성장의 증거

0개의 댓글