복합ID (1)

 

 

메인 프로젝트를 진행하면서 ERD를 사용해서 DB를 설계할 때 PK로 id 칼럼을 따로 만들 필요가 없어서 외래키 2개를 묶어서 테이블의 PK로 사용하도록 하는 테이블이 몇가지 있었다.

보통의 테이블에선 PK로 id 칼럼을 만들지만 '다대다' 연관관계에 있는 테이블은 중간에 테이블을 생성해서 '1대다', '다대1' 로 나눠주어야 서로 참조할 수 있기 때문에 중간에 데이터는 안들어가고 두 테이블의 PK만 가지고 있는 테이블이 생겼다.

메인 프로젝트(냥빌리지) ERD 일부

위와 같이 FK 2개만 가지고 테이블을 생성하였기 때문에 두개의 FK를 테이블의 PK로 사용한다.

DB에 테이블 생성할 때는 테이블을 먼저 다 생성한 다음 PK 제약조건으로 'TagToBoard'의 'boardId'와 'boardTagId'를 PK로 만든 후 외래키 제약 조건을 걸어주면 설정이 완료 된다!

 

그런데 Spring에서는 Entity에 PK를 하나밖에 지정하지 못하기 때문에 buid error가 발생한다.

해결 방법으로는 크게 3가지가 있는데 'Spring 복합 PK' 라고 검색하면 자세한 글들이 많다.

그중에 우리팀은 @IdClass 를 이용한 방법을 사용하였다.

사실 이 방법이 가장 간단한것 같다.

 

먼저 PK로 사용할 변수들에 @Id 애너테이션을 붙여준다. (2개 사용하므로 2개에 각각 붙여준다.)

먼저 Id를 묶어줄 Id 클래스를 만들어야 한다. 주로 TagToBoardId 이런식으로 ~Id 라고 지으면 나중에 보기 편하다!

그리고 Serializable을 구현한 구현체로 만들어 준다.

 

그리고 Id 클래스 위에 3가지 애너테이션을 꼭 추가해주어야 한다.

1. @Data

2. @NoArgsConstructor

3. @AllArgsConstructor

Id 클래스의 필드로 TagToBoard의 Id 필드 이름을 그대로 넣어준다.

이때 DB에 실제 저장되는 타입으로 넣어주어야 한다!!

예를 들어 JPA 를 사용하기 때문에 클래스 객체로 참조하였지만 실제 PK에 값은 boardId와 boardTagId값인 Long타입으로 들어갈 거기 때문에 Long 으로 해야한다. 변수명은 동일하게 지어준다.

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TagToBoardId implements Serializable {
    private Long board;
    private Long boardTag;
}

 

그리고 다시 TagToBoard 로 돌아와서 클래스 위에 @IdClass(TagToBoardId.class) 애너테이션을 추가해준다.

@Getter
@Entity(name = "TAG_TO_BOARD")
@NoArgsConstructor
@IdClass(TagToBoardId.class)
public class TagToBoard {
    @Id
    @ManyToOne
    @JoinColumn(name = "BOARD_ID")
    @JsonBackReference
    private Board board;

    @Id
    @ManyToOne
    @JoinColumn(name = "BOARD_TAG_ID")
    @JsonBackReference
    private BoardTag boardTag;
}

이렇게 묶어주면 오류 없이 복합 PK를 사용할 수 있다.

그리고 repository를 JpaRepository를 extends 해서 사용할 경우 id에 보통은 Long 등 숫자 타입이 들어가는데 대신에 생성한 id 클래스명(TagToBoardId)을 작성해주면 된다!

public interface TagToBoardRepository extends JpaRepository<TagToBoard, TagToBoardId> {
}

 

 

 

테이블명이나 칼럼명이 MariaDB 예약어에 등록되어 있으면 생성할 때 오류가 발생한다.

▷ MariaDB 예약어 목록

 

 

ddl auto를 사용하지 않고 DB에서 직접 테이블을 생성하다보면 제약조건이 꼬이거나 하는 문제가 발생할 수 있다.

이때 제약조건을 확인할 수 있는 쿼리문이 있어서 같이 올려놓는다.

모든 제약조건 확인하는 쿼리

SELECT *
FROM information_schema.table_constraints;

 

 

 

'DATABASE' 카테고리의 다른 글

[MySQL] 데이터베이스 테이블 생성 후 column 속성 변경  (0) 2022.09.06
[MySQL] 유용한 쿼리문  (2) 2022.09.03
1