I can do it(Feat. DEV)

[Spring Data JPA]복합키 설정(PK가 2개 이상일 때) 본문

개발자 모드/응용

[Spring Data JPA]복합키 설정(PK가 2개 이상일 때)

까짓거 해보자 개발자 2023. 11. 6. 15:37
728x90
1. TMI(글 작성 계기)

 

새로운 프로젝트를 개발 중에 로그인 기능을 추가하던 중

 

유저 테이블과 관련된 유저 권한 테이블에서 PK가 2개인 것을 발견..?

 

JPA를 사용하고 있었지만 PK가 두 개인 건 설정해 본 적이 없는 필자는 

 

그냥 냅다 @id를 각 컬럼에 붙였음.

 

 

역시 에러가 뜸... 찾아보니 ID 값이 두 개라서 매핑 오류가 떴다는 것(당연하지만)

 

그래서 방법을 찾던 중 알게 된 방법 2가지!!!

 

1. @Embeddable 및 @EmbeddedId 설정(객체지향에 더 가까운 방법)

 

2. @IdClass 설정(RDB에 가까운 방법)

 

인데 결국 PK 클래스를 만들어서 Serializable 을 implements 하고 각각 설정을 해주는 방식임.

 

그럼 설정하는 방식을 알아보겠음🤗

 

참고로 필자는 1번 방법을 사용하여 복합키를 설정하였음.


 

1. @Embeddable 및 @EmbeddedId 설정(객체지향에 더 가까운 방법)

 

@Data
@Entity
@AllArgsConstructor	//전체 생성자
@NoArgsConstructor	//기본 생성자
@Table(schema = "com",name = "cmt_user_right")
public class UserRight{	//유저 권한 테이블

    @EmbeddedId		//1번
    private UserId id;
    
//    @Column(name = "user_id")         
//    private String userId;       PK
    
//    @Column(name = "user_right")
//    private String userRight;     PK    

    @Column(name = "sys_type")
    private String sysType;

    @Column(name = "sys_date")
    private LocalDateTime sysDate;

    @Column(name = "user_desc")
    private String userDesc;
}

 

이런 식으로 유저 권한 테이블이 있었는데,

 

DB 툴로 확인했을 때 유저 권한 테이블은 userId, userRight 이 두 컬럼이 pk로 설정되어 있었음.

 

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable				//2번
@AllArgsConstructor		//전체생성자
@NoArgsConstructor		//기본 생성자
@EqualsAndHashCode		//equals, hashCode
@Data
public class UserId implements Serializable {	
    @Column(name = "user_id")		//3번
    private String userId;
    @Column(name = "user_right")
    private String userRight;

}

 

먼저 두 키를 포함한 식별자 클래스(UserId)를 생성 후 Serializable 인터페이스를 구현함.

 

그 후 1번처럼 @EmbeddedId 어노테이션을 붙여준 뒤 식별자 클래스 타입으로 변경해 줌.

 

다음 식별자 클래스 상단에 2번처럼 @Embeedable 어노테이션 선언하고, 3번처럼 키 컬럼을 설정하면 됨.

 

그리고 equals, hashCode를 구현해야 하며 기본 생성자가 있어야 함.

 

또 식별자 클래스(UserId)는 public이어야 한다는 점.

 

@Repository
public interface UserRightRepository extends JpaRepository<UserRight, UserId> {
    List<UserRight> findByIdUserId(String userId);	//아이디 별 유저 권한 불러오기
}

 

위와 같이 설정했다면 이제 repository 설정을 위처럼 하면 되는데...(필자는 Spring Data JPA 사용 중..👍)

 

유저 아이디별 권한 목록을 불러오며, UserRight 엔티티의 Id - UserId(식별자 클래스)의 userId

 

해서 findBy/Id/UserId 이런 식으로 명명규칙을 지켜주면서 선언하였음. 

 

그리고 JpaRepository의 제너릭 타입에

 

Entity Class와 Entity Class의 Key 값(UserId, 식별자클래스)을 위와 같이 넣어주면 됨!!


 

2. @IdClass 설정(RDB에 가까운 방법)

 

@Data
@Entity
@AllArgsConstructor	//전체 생성자
@NoArgsConstructor	//기본 생성자
@IdClass(UserId.class)	//1번
@Table(schema = "com",name = "cmt_user_right")
public class UserRight{	//유저 권한 테이블

    @Id	//2번
    @Column(name = "user_id")         
    private String id;      //UserId.id와 매칭
    
    @Id	//2번
    @Column(name = "user_right")
    private String right;     //UserId.right와 매칭

    @Column(name = "sys_type")
    private String sysType;

    @Column(name = "sys_date")
    private LocalDateTime sysDate;

    @Column(name = "user_desc")
    private String userDesc;
}

 

@IdClass 설정은

 

식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 함.

 

마찬가지로 Serializable 인터페이스를 구현해야하고 equal, hashCode를 구현해야 함.

 

또한 기본 생성자가 있어야하고 식별자 클래스는 public이어야 함.

 

 

728x90

 

 

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@AllArgsConstructor		//전체생성자
@NoArgsConstructor		//기본 생성자
@EqualsAndHashCode		//equals, hashCode
@Data
public class UserId implements Serializable {	
    private String id;
    private String right;

}

 

이런 식으로 식별자 클래스를 만들어 주면 됨!!!

 


 

@IdClass or @EmbeddedId  어떤 어노테이션을 사용하여 구성할지는 각자 장단점이 있기 때문에 

 

독자님들이 구현하고 싶은데로 진행하면 될 듯함.

 

선언하는 방식이 조금 다르고  실제로 쿼리를 조회한 후에 값을 조회할 때도 차이가 조금 있다고 함😅

 

필자도 아직 자세히는 몰라서 다음엔 더 자세히 포스팅 해보겠음👍 이상 끝.🤗

 

 

 

📢참고 사이트

 

https://brightstarit.tistory.com/53

 

[JPA] 복합 키와 식별 관계 매핑

식별관계와 비식별 관계 데이터베이스 테이블 사이에 관계는 외래 키가 기본 키에 포함되는지 여부에 따라 식별 관계와 비식별 관계로 구분된다. 식별 관계 식별 관계는 부모 테이블의 기본 키

brightstarit.tistory.com

 

 

728x90