jae_coding

[Spring JPA] 연관관계 매핑 본문

Spring, java/Spring_JPA

[Spring JPA] 연관관계 매핑

재코딩 2022. 9. 10. 16:19
반응형

목차

  • 단방향 연관관계
  • 양방향 연관관계와 연관관계의 주인

 

목표

  1. 객체와 테이블 연관관계의 차이에 대한 이해
  2. 객체의 참조와 테이블의 외래 키 매핑
  3. 방향, 다중성, 연관관계의 주인에 대한 용어 이해

 

 

0. 예제 시나리오

  • 회원과 팀이 있다.
  • 회원은 하나의 팀에만 소속될 수 있다.
  • 회원과 팀은 다대일 관계이다.
  • 객체 Diagram

  • 테이블 Diagram

 

1. 단방향 연관관계

Member Entity

package hellojpa;

import javax.persistence.*;
import java.util.Date;

@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name = "member_id")
    private Long id;

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

    @Column(name = "team_id")
    private Long teamId;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Long getTeamId() {
        return teamId;
    }

    public void setTeamId(Long teamId) {
        this.teamId = teamId;
    }
}

Team Entity

package hellojpa;

import javax.persistence.*;

@Entity
public class Team {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "team_id", nullable = false)
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Main

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;


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("teamA");
            em.persist(team);

            //멤버 저장
            Member member = new Member();
            member.setUsername("memberA");
            member.setTeamId(team.getId());
            em.persist(member);

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

DB Checking

 

조회 기능 (객체지향스럽지 않음)

//멤버 조회
Member findMember = em.find(Member.class, member.getId());
Long findTeamId = findMember.getTeamId();
Team findTeam = em.find(Team.class, findTeamId);

테이블에 대한 모델링을 하지 않으면 협력 관계를 만들 수 없다.

객체와 테이블 사이에는 외래 키와 참조에 대한 차이점이 존재한다.

 

 

단방향 연관관계를 이용한 해결방법

Member: Many,  Team: One의 관계로 JoinColumn.

 

@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
//멤버 저장
Member member = new Member();
member.setUsername("memberA");
member.setTeam(team);
em.persist(member);

//멤버 조회
Member findMember = em.find(Member.class, member.getId());
Team findTeam = em.find(Team.class, findMember.getTeam());

결과: 팀의 id없이 바로 team객체 조회 가능

더욱 객체지향스러운 코드로 변경이 완료된 것을 확인 할 수 있다.

 

2. 양방향 연관관계와 연관관계의 주인

매우 중요 !!       배경(객체 (참조), 테이블(외래 키) 패러다임 차이를 이해해야함)

 

예제를 업그레이드하는 방식으로 진행

  • 객체 Diagram

  • 테이블 Diagram

객체의 입장에서는 Team에 member 리스트를 넣어주어야 양쪽으로 참조를 할 수 있다.

하지만, 테이블의 입장에서는 member에서 외래키를 주어준다면 양쪽으로 연관관계를 지닐 수 있다.

 

따라서 아래와 같이 리스트를 생성해주어야 한다.

 

Team

@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();

Main

//팀 멤버 조회
List<Member> members = findMember.getTeam().getMembers();
for (Member m : members) {
    System.out.println("m.getUsername() = " + m.getUsername());
}

 

mappedBy를 왜, 언제 사용하는 것인가?

객체와 테이블에 연관관계를 맺는 차이를 이해해야 한다.

  1. 객체 연관관계 (2개)
    1. 회원 👉 팀 (단방향)
    2. 팀 👉 회원 (단방향)

객체의 양방향 관관계는 사실상 양방향 연관관계가 아닌 단방향 연관관계가 2개 있다는 것이다.

팀, 회원 중 하나만으로 외래 키를 관리해야한다 👉 연관관계의 주인이 필요하다 !

☝️연관관계의 주인만이 외래 키를 관리 (등록, 수정)

✌️주인이 아닌 쪽은 읽기만 가능 (mappedby)

주인: mappedBy사용 x, 주인이 아닌쪽 mappedBy사용

 

연관관계의 주인은 누구?

🌟 외래키가 있는 곳을 주인으로 해야한다.

DB를 보면, 외래키가 있는 곳이 N(다) 외래키가 없는곳이 1이다. (ManyToOne에서는 Many가 연관관계의 주인, One쪽은 mappedBy)

     

 

       2. 테이블 연관관계 (1개)

              회원 👈👉 팀 (양방향)     

              테이블은 외래 키 하나를 통해서 두 테이블의 연관관계를 관리해준다.

 

 

 

 

 

 

반응형
Comments