본문 바로가기

JPA

[JPA] 연관관계 매핑

연관관계 매핑

1. @OneToMany, @ManyToOne

 

@OneToMany와 @ManyToOne은 이름 그대로, 일대다, 다대일 연관관계를 정의한다.

우선 단방향 연관관계 매핑과 양방향 연관관계 매핑 코드를 살펴보자.

/*
    단방향 연관관계 매핑
*/
@Entity
public class A{

    @Column(name=B)
    @ManyToOne
    @JoinColumn(name="B_ID")
    private B b;

}

@Entity
public class B{

    @Id
    @Column(name="B_ID")
    private Long bId;

}

 

 

1. 연관관계 매핑 어노테이션인 @ManyToOne, @OneToMany...은 자신의 상태를 앞에 작성한다. 따라서, 위 코드에서는 A가 Many, B가 1에 해당한다.

 

2. @JoinColumn은 연관관계 매핑시 DB에 외래키에 해당하는 값을 매핑한다.

 

위 코드를 양방향 연관관계로 변경해보자.

/*
    양방향 연관관계 매핑
*/
@Entity
public class A{

    @Column(name="B")
    @ManyToOne
    @JoinColumn(name="B_ID")
    private B b;

}

@Entity
public class B{

    @Id
    @Column(name="B_ID")
    private Long bId;

    @Column(name="A")
    @OneToMany(mappedBy = "b") // mappedBy의 속성은 대상 필드의 변수명이다.
    private List<A> a; // 자바의 Collection, List, Set, Map중 하나를 사용한다
    
}

@OneToMany 어노테이션이 추가된 것을 볼 수 있다. @OneToMany어노테이션의 mappedBy속성은 패러다임의 불일치 문제를 해결하기위해 있는 속성으로 양방향 연관관계 매핑시 반드시 작성하여야 한다.

객체지향 패러다임에서 양방향 연결의 의미는 조금 다르다. 객체지향에서는 객체사이의 양방향 연결을 맺기 위해 각 객체에 상대 객체의 필드를 만든다. 이는 두 개의 참조를 만드는 것 으로, 하나의 외래키를 갖고 양방향 연결을 하는 테이블과는 차이가 있다. 이러한 이유 때문에, mappedBy속성을 이용해 연관관계의 주인을 지정해 주는것이다.

 

일대다, 다대일 관계에서 연관관계의 주인은 항상 '다' 쪽이 갖는다. 따라서, mappedBy속성은 OneToMany에만 설정할 수 있다. (이는 테이블에서 외래키의 주인이 누가 되는지 생각해보면 쉽게 이해가 될 것 이다.)

 

2. @OneToOne

@OneToOne은 1:1 연관관계 매핑을 의미한다.

@OneToOne관계에서는 어느 곳이나 외래키를 가질 수 있다.

/*
    양방향 연관관계 매핑
*/
@Entity
public class A{

    @Column(name="B")
    @OneToOne
    @JoinColumn(name="B_ID")
    private B b;

}

@Entity
public class B{

    @Id
    @Column(name="B_ID")
    private Long bId;

    @Column(name="A")
    @OneToOne(mappedBy = "b")
    private A a;
    
}

 

3. 다대다 @ManyToMany

데이터베이스에서는 다대다 연결을 하기위해서, 보통 중간테이블을 하나 연결한다. 따라서 다대다 연결은 다음과 같이 만들 수 있다.

@ManyToOne -> @OneToMany <- @ManyToOne

/*
    양방향 연관관계 매핑
*/
@Entity
public class A{

    @Id
    @GeneratedValue
    @Column(name="A_ID")
    private Long aId;

    @Column(name="AB")
    @OneToMany(mappedBy="a")
    private List<AB> aB;

}

@Entity
public class B{

    @Id
    @Column(name="B_ID")
    private Long bId;

    @Column(name="AB")
    @OneToMany(mappedBy="b")
    private List<AB> aB;
    
}

@Entity
public class AB{

    @ID
    @GeneratedValue
    @Column(name="AB_ID")
    private Long abId;

    @ManyToOne
    @JoinColumn(name="A_ID")
    private A a;
    
    @ManyToOne
    @JoinColumn(name="B_ID")
    private B b;
    
}

A와 B의 다대다 연결 관계를 풀어내기위해 AB라는 중간계층을 만든것을 볼 수 있다.

이 것 외에도 @ManyToMany를 사용하여 편하게 만들 수 있지만, 일반적으로 AB와같은 중간계층에 매핑 정보 외에 다른 정보를 담고 있는 경우가 많으므로 이는, 실무에서 사용하기에는 무리가 있다. 따라서, 다소 귀찮더라도 위 와 같은 방법을 고수하는것이 좋아보인다.