개발놀이터

JPA 복합 기본 키 (Composite Primary Key) 본문

JPA/JPA

JPA 복합 기본 키 (Composite Primary Key)

마늘냄새폴폴 2023. 6. 21. 20:19

이번 포스팅에선 JPA의 복합 기본 키에 대해서 알아보겠습니다. 

 

사실 이 내용을 공부하면서 이게 대체 왜 필요하지..? 싶은 내용이었습니다. 도저히 실제 애플리케이션에서 사용할 것 같지 않은 개념이라 조금 당황했지만 이것도 엄연히 JPA의 스펙 중 하나이기 때문에 놓치고 싶지 않았습니다. 

 

한번 어떤 내용인지 알아보죠!

 

JPA 복합 기본 키

우선 복합 기본 키라는게 어떤 것인지부터 알아야겠습니다. 

 

복합 기본 키 혹은 복합 키로 잘 알려진 영어로 Composite Primary Key는 컬럼들이 한 행이 보장되는 유니크함을 결합될 때 테이블 안에서 각각의 행들이 유니크하게 식별되는 두개 이상의 키입니다. 

 

이건 왜 사용할까요? 우리가 JPA를 사용할 때를 생각해볼 필요가 있습니다. 

 

만약 이름이 홍길동인 사람을 찾아야 한다고 가정해봅시다. 그래서 JPA로 쿼리 메서드를 만듭니다. 

 

public interface MemberRepository extends JpaRepository<Member, Long> {
	
    Member findByName(String name);
}

이러면 한 두명이 아니니까 리턴값을 Member로 받을 수 없을겁니다. 

 

그래서 이렇게 바꿨습니다. 

 

public interface MemberRepository extends JpaRepository<Member, Long> {
	
    List<Member> findByName(String name);
}

근데 이렇게 해놓으면 어떤 사람이 내가 찾는 사람일까요? 홍길동이 여러명이니까 누가 누구지?

 

이 때 등장하는게 복합 키 입니다. 예컨대 이름이 홍길동이고 네이버에 근무하는 사람을 찾고 싶다고 쿼리를 날리는겁니다. 

 

그럼 아마 몇명 안나올겁니다. 그럼 문제가 해결됐습니다. 그리고 이게 두개가 아니고 여러개면 더 특정할 수 있을겁니다. 

 

이런식으로 찾게 되면 굳이 기본키가 아니더라도 내가 원하는 데이터를 특정해서 찾을 수 있게 됩니다. 

 

자 이제 어떻게 사용하는지에 대해서 알아보죠. 

 

방법에는 두 가지가 있습니다. @IdClass 어노테이션과 @EmbeddedId 어노테이션을 사용하는 방법이죠. 

 

JPA 복합 기본 키 어떻게 사용하나?

@IdClass

먼저 기본 키가 될 집합이 되는 클래스를 만듭니다. 

 

import lombok.NoArgsConstructor;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentID implements Serializable {
	private String studentId;
	private String name;
}

 

그리고 엔티티 클래스를 만들어줍니다. 

 

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "student")
@IdClass(StudentID.class)
public class Student implements Serializable {
	@Id
	@Column(name = "student_id")
	private String studentId;
	
	@Id
	private String name;
	
	@Column(name = "school_id")
	private int schoolId;
	private int score;
}

여기서 주의하셔야 할 점은 복합 키가 되어야 할 클래스와 엔티티 클래스 모두 복합 키를 사용할 것이라면 Serializable을 implements 해줘야합니다. 

 

Serializable은 직렬화를 나타내는 클래스입니다. 직렬화를 위해서라면 반드시 선언해줘야하는 클래스이죠. 같은 느낌으로 Redis 객체와 엔티티 객체를 매핑할 때도 직렬화 역직렬화가 필요합니다. 

 

그리고 Repository 클래스를 만들어줍니다. 

 

import org.springframework.data.jpa.repository.JpaRepository;
import com.spring.jpa.dto.Student;
import com.spring.jpa.dto.StudentID;

public interface StudentRepository extends JpaRepository<Student, StudentID> { // 제네릭 타입: <엔티티 클래스, 엔티티 클래스의 기본키>

}

 

이제 이대로 사용하시면 끝입니다. 

 

@EmbeddedId

@EmbeddedId 역시 사용법은 비슷합니다. 

 

import lombok.NoArgsConstructor;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class StudentID implements Serializable {
	@Column(name = "student_id")
	private String studentId;
	
	private String name;
}
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "student")
public class Student implements Serializable {
	
	@EmbeddedId
	private StudentID stduentID;
	
	@Column(name = "school_id")
	private int schoolId;
	private int score;
}

복합 키를 모아놓은 클래스와 엔티티 클래스를 만듭니다. 그리고 Repository클래스를 만들면 끝입니다

 

import org.springframework.data.jpa.repository.JpaRepository;
import com.spring.jpa.dto.Student;
import com.spring.jpa.dto.StudentID;

public interface StudentRepository extends JpaRepository<Student, StudentID> { // 제네릭 타입: <엔티티 클래스, 엔티티 클래스의 기본키>

}

 

둘 중 어느 것을 사용해야 하지?

사실 둘의 성능 차이나 그런건 없습니다. 그냥 둘 중 편한거 사용하시면 됩니다. 

 

저는 만약 둘 중 사용한다면 좀 더 객체지향스럽게 보이는 @EmbeddedId를 사용하지 않을까 싶습니다. 

 

 

복합 기본 키의 장점

복합 기본 키를 사용하면 그냥 사용하는 것보다 조금 더 직관적으로 클래스를 표현할 수 있습니다. 

 

또한, 정규화를 간단하게 이뤄낼 수 있다는 장점도 있죠. 혹은 @ManyToMany 상황에서 사용할 수도 있습니다. 

 

 

근데... 굳이 사용해야 하나? (feat. ChatGPT)

이런 의문이 드실 수도 있습니다. 저도 이런 의문이 들었습니다. 

 

이거 얻다 쓰지? 

 

그냥 컬럼 명으로 여러개 조건을 달면 되는 것이고, JPA는 엔티티 클래스에서 객체로 매핑하는 방법들을 제공하는데 왜 굳이 저렇게까지 힘들게 해야하나 싶었습니다. 

 

실제로도 복합 기본 키를 사용하는 것은 일반적인 상황은 아닙니다. 특별한 상황에서만 쓰는 것이죠. 

 

그리고 많은 개발자들이 간단한 기본 키를 더 선호합니다. 그 이유도 여러가지가 있는데요. 

 

  • 간단함 : 간단하게 기본키 하나만 두는 것이 애플리케이션을 관리하고 이해하는데 더 쉽습니다. 
  • 성능 : 기본키 하나만 두는 것이 애플리케이션의 성능에도 좋습니다. 데이터베이스에선 다양한 연산이 있는데 인덱스나, 검색, 조인 등을 실행할 때 훨씬 빠른 속도를 보여줍니다. 
  • 프레임워크와 호환성 : JPA를 포함한 많은 프레임워크에서 기본 키를 하나만 두는 것을 전제로 하고 있습니다. 그래서 JPA에서도 @OneToOne, @ManyToOne, @OneToMany와 같은 어노테이션으로 엔티티들 사이의 관계를 매핑하는데 더 쉽게 만들어주는 어노테이션을 제공합니다. 

그럼 복합 기본 키가 JPA의 스펙에 들어있는 이유는 뭘까요? 그것도 몇 가지 이유가 있습니다. 

 

  • 오래된 데이터베이스 아키텍처 : 만약 우리가 복합 기본 키를 사용하는 데이터베이스와 자바 애플리케이션을 매핑해야 할 때 사용해야합니다. 
  • @ManyToMany 매핑 : 다대다 관계에서 테이블을 조인하기 위해서 JPA는 다대다 조인을 위한 테이블이 하나 더 만듭니다. 이 때 종종 복합 기본 키를 사용해서 테이블을 만듭니다. 

GPT가 추천해주기를

 

"설령 복합 기본 키를 사용해야 하더라도 복합 기본 키를 사용하는 것은 우리의 애플리케이션의 추가적인 복잡도를 야기할 수 있습니다. 그러니 특별한 이유에 의한 적절한 해결책을 위해 조심해서 고민해봐야 합니다."

 

 

마치며

여기까지 JPA의 복합 기본 키에 대해서 알아봤습니다. 복합 기본 키를 정리하자면 새로운 프로젝트에는 웬만하면 싱글 기본 키를 사용하고 오래된 데이터베이스 아키텍처와 JPA를 매핑해야 하는 상황에서 복합 기본 키를 사용하면 될 것 같습니다. 

 

아무래도 JPA는 데이터베이스와 객체를 연결해줘야 하는 역할이 있기 때문에 데이터베이스에서 제공하는 복합 기본 키를 똑같이 지원할 수 밖에 없을 듯 싶습니다. 

 

긴 글 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요~

 

 

출처 (Thanks Chat GPT)

https://www.baeldung.com/jpa-composite-primary-keys

 

Composite Primary Keys in JPA | Baeldung

Learn how to configure a JPA entity for more than one primary key column, diving into the tradeoffs between @EmbeddedId and @IdClass.

www.baeldung.com

https://www.simplilearn.com/tutorials/sql-tutorial/composite-key-in-sql

 

Composite Key in SQL: Your Ultimate Guide to Mastery [Updated]

Read this composite key in SQL tutorial to know what is a composite key in SQL, the syntax to composite key in SQL, and how to use the composite key in SQL.

www.simplilearn.com

https://www.geeksforgeeks.org/composite-key-in-sql/

 

Composite Key in SQL - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org