본문 바로가기
Spring 이해하기

[JPA] JoinColumn vs mappedBy

by simplify-len 2021. 6. 13.

Photo by  Bermix Studio  on  Unsplash

mappedBy@JoinedColumn 에 대해서 알아보기.

@Entity
public class Company {

      ...

    private String name;

    @OneToMany(mappedBy = "company",
            orphanRemoval = true,
            fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    private List<Branch> branchs = new ArrayList<>();
        ...
}
@Entity
public class Branch {

    ...

    private String branchName;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "companyId",
            foreignKey = @ForeignKey(name = "companyToBranch"))
    private Company company;

    ...
}

외래키를 관리하는 주인 엔티티에 mappedBy가 있을 경우, 맵핑 테이블을 만들지 않습니다.

이 상태에서 CompanyBranch의 엔티티 데이터를 어떻게 넣어야할까요?

@Test
void company2() {
  Branch seoul = new Branch( "seoul");
  ArrayList<Branch> branchs = new ArrayList<>();
  Company company = new Company("김정규", branchs);
  seoul.setCompany(company);
  branchs.add(seoul);
  companyRepository.save(company);
}

mappedBy가 가리키는 곳의 Company 관점에서 데이터를 Persist 합니다. 물론 Branch 에도 어떤 Company 를 넣어야 하는지 알려주어야만 합니다.

그렇다면, Branch 에서 Company 를 set 상태에서 Persist 를 하게 되면 저장이 될까요?

@Test
void company2() {
  Branch seoul = new Branch( "seoul");
  ArrayList<Branch> branchs = new ArrayList<>();
  Company company = new Company("김정규", branchs);
  seoul.setCompany(company);
  branchs.add(seoul);
  branchRepository.save(seoul);
}

image-20210613150455728

위와 같이 Null 이 들어갑니다. 이유는 MappedByCompany 를 가르키기 때문입니다.

그럼 MappedBy 가 빠지면 될 것인가? 결과부터 이야기하면 그렇지 않다 입니다.

왜냐하면, Branch 쪽에 붙어있는 @JoinColumn 때문입니다. @JoinColumn 가 이미 Company 와 결합하고 있다는 사실을 나타내기 때문에 위와 같이 Null 로 들어갑니다.

그럼다면 MappedBy@JoinColumn 를 제거 한다면 될까요?

Branch 를 저장할 때 Company도 같이 저장될까요?

@ManyToOne(fetch = FetchType.LAZY)
private Company company;

또 안됩니다. 왜 안될까요? 이제 슬슬 화나기 시작합니다. 왜안될까요? 또 다시 결론부터 이야기하면, Company가 현재 Persist상태가 아니기 때문에 안됩니다.

그렇다면 CompanyPersist 를 시키게 되면?

@Test
void branch() {
  Branch seoul = new Branch( "seoul");
  ArrayList<Branch> branchs = new ArrayList<>();
  Company a = new Company("김정규", branchs);
  Company save = companyRepository.save(a);
  seoul.setCompany(save);
  branchRepository.save(seoul);
}

image-20210613151108968

드디어!!! 저장이 되었네요.

관례처럼 @OneToMany 에 붙여 사용하던 @Mappedby 에 대해서 하나씩 분해해보면서 차례대로 살펴봤습니다.

이번에는 @JoinColumn 을 두고 @Mappedby 제거할 때는 어떤 일이 일어날까요?

@Test
void no_JoinColumn() {
  Branch seoul = new Branch( "seoul");
  ArrayList<Branch> branchs = new ArrayList<>();
  branchs.add(seoul);
  Company company = new Company("김정규", branchs);
  seoul.setCompany(company);
  companyRepository.save(company);
}

image-20210613152415265

정상적으로 데이터가 들어갑니다. mappedBy 가 없음에도 불구하고, 데이터가 정상으로 잘들어갔습니다.

어떻게 된걸까요?

MappedBy 는 주인관계를 결정시켜주는 용도가 맞습니다. 그러나 약한 결합을 의미합니다. 즉, MappedBy 가 없다고 하더라고, @JoinColumn가 있다면, 이 관계는 @JoinColumn 에 의해서 주인이 결정된 상태를 의미합니다. 그러므로, 데이터에 값이 들어가는데 있어서 문제가 되지 않는 것입니다.

그 외에 알아놓으면 좋은점

그러나 만약 mappedBy@JoinColumn 가 없다면, 중간에 맵핑 테이블을 만듭니다.

Hibernate: 

    create table branch (
       id bigint generated by default as identity,
        branch_name varchar(255),
        company_id bigint,
        primary key (id)
    )
Hibernate: 

    create table company (
       id bigint generated by default as identity,
        name varchar(255),
        primary key (id)
    )
Hibernate: 

    alter table branch 
       add constraint FK14f9k065wqeubl6tl0gdumcp5 
       foreign key (company_id) 
       references company

    create table branch (
       id bigint generated by default as identity,
        branch_name varchar(255),
        company_id bigint,
        primary key (id)
    )
Hibernate: 

    create table company (
       id bigint generated by default as identity,
        name varchar(255),
        primary key (id)
    )
Hibernate: 

    create table company_branchs (
       company_id bigint not null,
        branchs_id bigint not null
    )
Hibernate: 

    alter table company_branchs 
       add constraint UK_pnrlwntrhoehu7pf7jdrnue99 unique (branchs_id)
Hibernate: 

    alter table branch 
       add constraint FK14f9k065wqeubl6tl0gdumcp5 
       foreign key (company_id) 
       references company
Hibernate: 

    alter table company_branchs 
       add constraint FKhf03d5wcok0kvhpnwsu0eu5lk 
       foreign key (branchs_id) 
       references branch
Hibernate: 

    alter table company_branchs 
       add constraint FK1pt4rkx3g0rd82s6d39e6y23a 
       foreign key (company_id) 
       references company

[참고자료]

https://stackoverflow.com/questions/11938253/jpa-joincolumn-vs-mappedby

댓글