개발지식

(JPA) mappedBy 완벽 이해!

우루쾅 2025. 7. 26. 08:06
728x90
반응형
SMALL

 

mappedBy는 JPA에서 양방향 연관관계를 매핑할 때 사용하는 중요한 속성입니다. 이 개념을 이해하려면, 먼저 양방향 연관관계가 무엇인지부터 살펴보고, 그 후 mappedBy의 의미와 역할을 코드 예시와 함께 단계적으로 설명하겠습니다!

 

✅ 1. 양방향 연관관계란?

엔티티 A와 엔티티 B가 서로 참조하는 관계를 말합니다.

예시:

  • Member가 Team에 소속되어 있고,
  • Team도 Member들을 알고 있을 때

즉, Member ↔ Team 관계

 

 

✅ 2. 관계 설정 시 주인(owner)과 비주인(inverse)이 존재

JPA는 연관관계의 주인만이 외래 키를 관리할 수 있습니다.
양방향 관계에서는 어느 쪽이 외래 키를 관리하는 주인인지 명확히 해야 합니다.
그때 사용하는 것이 바로 mappedBy입니다.

 

 

✅ 3. 예시로 보는 mappedBy

엔티티 클래스 설계

@Entity
public class Member {

    @Id
    @GeneratedValue
    @Column(name="MEMBER_ID")
    private Long id;

    @Column(name="USERNAME")
    private String username;

    @ManyToOne
    // 1. JoinColumn 에서 Team 테이블의 pk 를 셋팅
    // JoinColumn 은 관리한다는 의미(외래키가 있는 곳을 owner로 설정해야됨)
    // 보통 1:n 관계이면 n 이 연관관계 주인이 됨
    @JoinColumn(name="TEAM_ID")
    private Team team;
    
    }
@Entity
public class Team {

    @Id
    @GeneratedValue
    @Column(name="TEAM_ID")
    private Long id;
    private String name;

    // 2. Member 테이블에서 team 테이블의 pk 를 JoinColumn 으로 참조
    // 3. team pk 를 참조한 컬럼의 값을 mappedBy 로 셋팅
    // mappedBy 는 team에 의해서 관리가 된다는 의미!
    // mappedBy 는 읽기만 함
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
    
    }

핵심 포인트

항목 설명
@ManyToOne Member가 Team을 참조 (외래 키 team_id 소유)
@OneToMany(mappedBy = "team") Team은 Member들을 읽어오기만 함. mappedBy = "team"은 Member 클래스의 team 필드를 가리킴
 

✅ 4. 왜 mappedBy가 필요할까?

  • mappedBy를 사용하지 않으면 JPA는 두 테이블 모두 외래 키를 가지려 하고 중복 매핑 문제가 발생합니다.
  • mappedBy는 "나는 주인이 아니야. 외래 키는 상대방이 관리해."라고 선언하는 것.

 

 

✅ 5. 실제 사용 예시

package jpabook.jpashop;


import jpabook.jpashop.domain.Member;
import jpabook.jpashop.domain.Team;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {

            // 저장
            Team team = new Team();
            team.setName("A");
            em.persist(team);

            Member member = new Member();
            member.setUsername("member1");
            member.setTeam(team);
            em.persist(member);

            // 영속성 컨텍스트의 쿼리 sql 로 푸쉬
            em.flush();
            // 영속성 컨텍스트 클리어
            em.clear();

            Member findMember = em.find(Member.class, member.getId());
            // 4. 양방향 연관관계 환경 셋팅
            List<Member> members = findMember.getTeam().getMembers();

            for (Member m : members) {
                System.out.println("m : "+m.getUsername());
            }

            tx.commit();
        }catch(Exception e){
            tx.rollback();
        } finally{
            em.close();
        }

        tx.commit();
        emf.close();
    }
}

 

 

✅ 7. 정리

구분 설명
주인 Member.team (외래 키 있음)
비주인 Team.members (mappedBy = "team")
mappedBy 역할 외래 키를 가진 쪽이 아님을 명시
 
 

 

 

출처

- 김영한(자바 ORM 표준 JPA 프로그래밍 - 기본편)

 

 

728x90
반응형
LIST