TIL ... day 18 4주차 - Spring 3일차 연관관계 맵핑에 대한 이해... 22.05.30

BYEONGMIN CHOI·2022년 5월 30일
0

TIL(Today I Learned)

목록 보기
14/24

오늘의 회고록은 데이터테이블을 설계할때 jpa로 테이블간 연관관계에 대해 정리해보려합니다. 과제를 진행하며 게시판의 게시글과 각각의 게시글에 덧글을 관계를 설정하기 위해 찾아보다 이렇게 정리하게 되었습니다.

연관관계를 맵핑할 때 고려해야 하는 3가지

  • 다중성
  • 방향
  • 연관관계의 주인

다중성(Multiplicity)

연관관계에는 다음과 같은 다중성이 있습니다.

  • 일대일 OneToOne ( 1 : 1)
  • 일대다 OneToMany ( 1 : N )
  • 다대일 ManyToOne ( N : 1 )
  • 다대다 ManyToMany ( N : N )

방향(Direction)

  • 단방향
  • 양방향

연관관계의 주인(Owner)

객체 양방향 연관관계는 관리가 필요하다. \rightarrow 다대다

객체를 테이블에 맞춰 데이터 중심으로 모델링 하면, 협력관계로 만들 수 없다.

  • 객체를 테이블에 맞춰 모델링한 코드
package study.datajpa.dto;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/* 회원(Member) 엔티티*/
@Entity
public class Member {
    
    @Id @GeneratedValue
    private Long id;
    
    @Column(name = "USERNAME")
    private String name;
    
    @Column(name = "TEAM_ID")
    private Long teamId;
}

/* 팀(Team) 엔티티 */
@Entity
public class Team{
    @Id @GeneratedValue
    private Long id;
    private String name;
}

\rightarrow 무엇이 문제인가? DB에 저장 & 조회

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.setName("mamber1");
            member.setTeamId(team.getId());
            em.persist(member);
            tx.commit();
        }catch(Exception e ){
            tx.rollback();
        }finally {
            em.close();
        }

    }
}

-> 외래키 식별자를 직접 다루고 있어 조회할 때 해당 외래키를 가지고 조인 쿼리를 직접 짜야한다.

-> 외래키를 직접 관리하는 테이블에 맞춘 객체 모델링은 객체간의 협력관계를 만들 수 없고, 객체가 참조를 통해 연관객체를 찾는 다는 사상을 적용할 수 없다.

객체지향 모델링(객체 연관관계 사용)

package hellojpa;

import javax.persistence.*;

/* 회원(Member) 엔티티*/
@Entity
public class Member {

    @Id @GeneratedValue
    private Long id;

    @Column(name = "USERNAME")
    private String name;
    
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
		
		... getter, setter
}
  • @ManyToOne @JoinColumn 을 통해 멤버(Member)에서 팀(Team)을 참조하도록 했다.
try{
    Team team = new Team();
    team.setName("teamA");
    em.persist(team);

    Member member = new Member();
    member.setName("mamber1");
    member.setTeam(team);
    em.persist(member);
		
		em.flush();
		em.clear();

    Member findMember = em.find(Member.class, member.getId());
    Team findTeam = member.getTeam();
    
    tx.commit();
}catch(Exception e ){
    tx.rollback();
}finally {
    em.close();
}

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

  • 단방향에서 양방향이 된다는 것의 의미는 양측에서 서로를 참조할 수 있다는 것
  • 테이블 연관관계에서는 외래키를 가지고 양측에서 서로를 참조 가능
  • 객체에 List를 추가하여 양방향 연관관계를 만들어 준다.
@Entity
public class Team{
		...
		@OneToMany(mappedBy = "team")
		private List<Member> members = new ArrayList<>();
		...
}
  • 추가한 menbers를 확인하는 코드
Member findMember = em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();
for (Member member1 : members) {
    System.out.println("member1.getName() = " + member1.getName()); // member1.getName() = mamber1
}

연관관계의 주인과 mappedBy

  • 객체와 테이블간 연관관계를 맺는 차이를 이해해야함

객체와 테이블이 관계를 맺는 차이

  • 객체 연관관계 = 2개
    • 회원 -> 팀 연관관계 1개(단방향)
    • 팀 -> 회원 연관관계 1개(단방향)

  • 테이블 연관관계 = 1개
    • 회원 <-> 팀 연관관계 1개 (양방향)

양방향 관계란

  • 객체의 양뱡향 관계는 서로 다른 단방향 관계가 2개인 것
  • 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들면 된다.
    -A -> B(a.getB())
    -B -> A(b.getA())

둘 중 하나를 외래 키로 관리해야한다.

  • 연관관계의 주인(Owner) -> 양방향 매핑 규칙

    • 객체의 두 관계중 하나를 연관관계의 주인으로 지정
    • 연관관계의 주인만이 외래 키를 관리(등록, 수정)
    • 주인이 아닌쪽은 읽기만 가능
    • 주인은 mappedBy 속성을 사용하지 않는다.
    • 주인이 아니면 mappedBy속성으로 주인을 지정한다.

    참고

profile
스스로 성장하는 개발자가 되겠습니다.

0개의 댓글