DEV/Spring

[JPA] @JoinColumns 두 개 이상의 조인 컬럼 설정하기

l-eazzy 2023. 8. 6. 19:12

Entity 연관 관계 설정을 하다보면,

두 개 이상의 조인 관계를 나타내야하는 경우가 있다.

 

 

만약에 서비스 사용자(Member)게시글(Board) Entity가 존재하고,

게시글은 사용자의 고유 아이다(id)와 이름(name) 을 외래키(foreign key)로 가지고 있다고 해보자.

 

Member와 Board는 1:N 의 관계를 가질때,

Entity 는 아래와 같이 구성할 수 있을 것이다.

 

 

1. 구현

[Entity] Member.class

@Entity
@NoArgsConstructor
@Getter
@ToString
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String name;
    @Column
    private Integer age;

    @Builder
    public Member(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

 

[Entity] Board.class

@Entity
@NoArgsConstructor
@Getter
@ToString
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column
    private String title;
    @Column
    private String content;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumns({
            @JoinColumn(name = "member_id", referencedColumnName = "id"),
            @JoinColumn(name = "member_name", referencedColumnName = "name")
    })
    private Member member;


    @Builder
    public Board(Long id, String title, String content, Member member) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.member = member;
    }
}

 

Board 클래스에 Member 클래스의 연관관계를 표기할 때,

@JoinColumns() 어노테이션을 이용하면 두 가지 이상의 컬럼을 연결 할수있다.

  • name : board 테이블에 표기될 member 테이블 컬럼 이름을 표기
  • referencedColumnName : member 테이블에 정의된 컬럼 이름

 

 

2. 실행

애플리케이션을 실행 시켜 DB에 스키마 생성(create) 시키면,

아래 이미지처럼 2개의 컬럼이 FK 로 연결된 걸 볼 수 있다.

 

 

저장된 데이터를 조회 시,

Board 테이블 조회와 같이 join table로 Member 테이블의 id와 name 값을 기준으로 조회하는 것을 볼 수 있다.

 

 

 

3. 추가

구현 상 어려운 점은 없을 건데....

 

여기서 드는 궁금증!

'FetchType을 Lazy로 Member 조회 없이 가져오는가?' 였다.

 

그래서 Fetch Type 을 Lazy 로 바꾸고 조회를 진행해 보았다.

 

 

진행 결과,

FetchType.Lazy 로 설정하여도 Member의 name 컬럼을 찾아야하기에,

한번 더 Member를 select 하는 쿼리가 나가는 것을 볼 수있었다.

 

만약 컬럼이 하나만 연결되었다면

(If, Member id 컬럼)

 

해당 객체를 호출하지 않는 이상 Member를 조회하지 않았겠지만

연결된 컬럼이 name 도 포함되어있기에 함께 조회되는 것을 볼 수 있었다.

 

 

Jpa 연관관계 설계 상,

디폴트 값이 아래와 같이 설정 되어 있다.

 

ToOne 은 Fetch Eager

ToMany 는 Fetch Lazy

 

 

굳이 ManyToOne 에서 Lazy 를 하는 경우가 아니라면 조회에 문제는 없겠지만

 

혹시 여러 컬럼을 연결하고,

Lazy 로 설정하여 쿼리가 두번 나가고 있지는 않는지 점검해보는건 어떨까한다.

 

 

4. 참고 문서

https://stackoverflow.com/questions/56327228/avoid-jpa-fetch-eager-with-join-table

 

Avoid jpa fetch eager with join table

I have the next classes: A class User: @Entity @JsonRootName(value = "user") @Table(name = "web_users", schema = "t_dw_comercial") public class User { @Id private int userId; private S...

stackoverflow.com

 

728x90