내배캠 주요 학습/TIL : Today I Learned

JPA 외래키 설정, 복합키일 경우

chaeyoung- 2023. 6. 27. 13:42

 


DataBase Table Relationship

DataBase Table

 

 


Entity Relationship Diagram

Entity Relationship Diagram

 

1. Post와 User는 단방향 N : 1 관계이다.
2. Post는 User 테이블의 username 칼럼을 참조한다.

 

 

<< 기본키가 1개일 경우 >>

1. User, java

package com.sparta.myblog.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "users")
public class User {

    @Id
    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @OneToMany(mappedBy = "user")
    private List<Post> postList = new ArrayList<>();

    @Column(nullable = false)
    @Enumerated(value = EnumType.STRING)
    private UserRoleEnum role;


    public User(String username, String password, UserRoleEnum role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }
}

 

 

2. Post.java

package com.sparta.myblog.entity;

import com.sparta.myblog.dto.PostRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@Setter
@Table(name = "post")
@NoArgsConstructor
public class Post extends Timestamped {

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

    @Column(nullable = false)
    private String title;

    @ManyToOne
    @JoinColumn(name = "username", nullable = false)
    private User user;

    @Column(nullable = false, length = 500)
    private String contents;

    public Post(PostRequestDto requestDto, User user) {
        this.title = requestDto.getTitle();
        this.contents = requestDto.getContents();
        this.user = user;
    }

    public void update(PostRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.contents = requestDto.getContents();
    }

}

 

Post 클래스 내에서

    @ManyToOne
    @JoinColumn(name = "username", nullable = false)
    private User user;

@JoinColumn(name = "username ")

코드를 입력할 경우 Post 테이블에 username 이라는 명칭의 칼럼이 추가됩니다.

해당 칼럼은 users 테이블의 PK를 참조하는 외래키의 속성을 갖습니다.

 

@JoinColumn은 referencedColumnName 속성을 통해

users 테이블의 기본키인 username을 자동으로 참조합니다.

 

 

 

복합키의 경우

package com.sparta.myblog.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Id
    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @OneToMany(mappedBy = "user")
    private List<Post> postList = new ArrayList<>();

    @Column(nullable = false)
    @Enumerated(value = EnumType.STRING)
    private UserRoleEnum role;


    public User(String username, String password, UserRoleEnum role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }
}

 

 

그렇다면 User 테이블이 복합키일 경우는 어떨까?

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

    @Id
    @Column(nullable = false, unique = true)
    private String username;

현재 users 테이블의 기본키는 id , username 두개로 지정되어 있습니다.

Post 테이블에서 users 테이블의 복합키 모두를 외래키로 참조할 수 있을까?

 

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "user_id"),
            @JoinColumn(name = "user_name")
    })
    private User user;

위와 같이 설정할 경우 , post 테이블에 user_id, user_name 칼럼이 생성된다.

한 테이블에서 복합키를 통해 외래키를 여러개 지정할 수 있다는 의미이다.

 

 

 

 

 

마지막으로, 복합키 중 한개만 외래키로 참조할 수 있을까?

    @ManyToOne
    @JoinColumn(name = "username", nullable = false)
    private User user;

 

Failed to initialize JPA EntityManagerFactory: An association that targets entity 'com.sparta.myblog.entity.User' from entity 'com.sparta.myblog.entity.Post' has 1 '@JoinColumn's but the primary key has 2 columns

users 테이블에 기본키가 두개 이므로

두개 모두 설정해주어야 하는 것 같습니다.

찾아보면 방법이 있지 않을까 싶어서 또다른 방법을 찾아보고 해당 글에 링크 걸어두도록 하겠습니다.

 

 

 

 


references : 

[JPA] @JoinColumn 확실히 알고가기!!! (tistory.com)

 

[JPA] @JoinColumn 확실히 알고가기!!!

안녕하세요 오늘은 JPA 주제로 글을 써보도록 하겠습니다. 테이블들간 연관관계를 설정해 줄때 일대다(1:N) 관계일때 @JoinColumn 어노테이션을 사용해서 해당 컬럼의 이름을 설정해줍니다.... 근데!!

boomrabbit.tistory.com