Free Lines Arrow
본문 바로가기
DataBase/JPA

[JPA] 연관관계 매핑기초1: 단방향 연관관계

by skahn1215 2021. 8. 1.
728x90
반응형

단방향 연관관계

  • 단방향 연관관계를 알아본다.
  • 객체와 테이블 연관관계의 차이를 이해.
  • 객체의 참조와 테이블의 외래 키를 매핑

 

 

 

 

용어

  • 방향(Direction): 단방향, 양방향 존재
  • 다중성(Multiplicity): N:1, 1:N, !:1, N:M 이해
  • 연관관계 주인(Owner): 객체 양방향 연관관계는 관리 주인이 필요하다.

 

 

 

예제 시나리오

  • 회원과 팀이 있다.
  • 회원은 하나의 팀에만 소속된다.
  • 회원과 팀의 N:1 관계다.

 

 

 

객체와 테이블 연관관계 ERD

  • 그림 처럼 객체와 테이블의 연관관계를 만들어 주어야한다.
  • 멤버와 팀은 N:1 관계 이고 멤버는 TEAM_ID 를 FK 로 사용하고 있다.
  • 아래처럼  멤버만 팀을 참조 한방향으로만 참조하기 때문에 단방향이라고 한다.

 

 

 

 

데이터 중심의 모델링

연관관계 매핑 없이 데이터 중심으로 모델링예제

보기 쉽게 getter setter 는 생략 했습니다.

 

Member

@Entity
public class Member {

    @Id //PK 설정
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "name", nullable = false, length = 100)
    private String username;

    @Column(name = "TEAM_ID")
    private Long teamId;
}

 

Team

package relationmapping;

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


@Entity
public class Team {

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

    private String name;
}

 

Main

public class RelationMappingEx {
    public static void main(String[] args) {
        // persistence.xml 의 persistence-unit name="hello" 를 넘긴다.
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        // 매니저를 꺼내온다.
        EntityManager em = emf.createEntityManager();

        // 트랜잭션 얻어오고 실행한다.
        // JPA 는 트랜잭션 안에서 수행되어야 한다.
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        // exception 처리를 위해 try catch 문을 반드시 사용해야된다.
        try {
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);

            // 문제1
            // setTeamId 는 객체지향 스럽지가 않다.
            // setTeam으로 객체를 받아야 객체 지향 스럽다.
            Member member = new Member();
            member.setUsername("member1");
            member.setTeamId(team.getId());
            em.persist(member);

            // 문제2
            // 조회시 가져오는 과정을 두번 거쳐야 된다.
            memeber에서 teamId 후 entityManager 에서 Team 을 가져 와야한다.
            Member findMember = em.find(Member.class, member.getId());
            Team findTeam = em.find(Team.class, findMember.getTeamId());

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

 

 

 

 

문제점

문제1: Member에서 Team을 참조하기 위해 Team의 Id 값을 가지고 있다.
- 객체지향 스럽게 설계 하려면 Id 값이 아닌 Team 객체를 가지고 있어야 한다.

 

문제2: 조회시 무조건 두번의 과정을 거쳐야한다.
- Member를 찾고 Team의 Id 를 가져온다.
- Team 의 Id 로 다시 EntityManager 에서 Team을 가져와야 한다.

 

 

 

 

테이블과 객체의 갭차이

  • 테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다.
  • 객체는 참조를 사용해서 연관된 객체를 찾는다.

 

 

 

 

 

 

객체지향 모델링

 

객체지향 모델링 ERD

  • 아래그림은 객체 연관관계를 추가로 표현이된 ERD 이다.
  • 객체의 연관관계를 주어 보다 객체스럽게 설계를 할 수 있다.
  • Member의 기준으로 봤을때 Member 가 N, Team이 1  N:1 관계이다.

 

 

 

 

객체지향의 모델링

  • 다음 어노테이션으로 맵핑을 해준다.
  • @ManyToOne: N:1 을 표현하기 위해 써준다.
  • @JoinColumn(name = "TEAM_ID"): 객체 연관관계 에서 Team 과 테이블 연관관계를 맵핑해 주는 역할을 한다
  • 위 두개를 이용해 주면 아래 처엄 연관관계 맵핑을 해줄수 있다.

 

 

Member

package relationmapping;


import javax.persistence.*;

// 꼭넣어야 한다.
// JPA가 로딩 될때 해당 어노테이션을 보고 인식한다.
@Entity
//@Table(name = "USER") // 테이블명 지정
public class RelationMember {

    @Id //PK 설정
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "name", nullable = false, length = 100)
    private String username;

    // id 에서 객체로 변환

    public Long getId() {
        return id;
    }

    // 객체 모델링
    // Member 입장에서 Team 의 연관관계를 볼때
    // Member 는 N Team 은 1 이기 때문에
    // manytoone 을 써준다.

    // 객체 의 FK 인 Team 과 DB의 TEAM_ID 와 맵핑을 해줘야 한다.
    // 그럼 DB 와 객체를 맵핑해준것이다
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}

 

Team

package relationmapping;

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


@Entity
public class Team {

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

    private String name;
}

 

Main

package relationmapping;

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

public class RelationMappingEx {
    public static void main(String[] args) {
        // persistence.xml 의 persistence-unit name="hello" 를 넘긴다.
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        // 매니저를 꺼내온다.
        EntityManager em = emf.createEntityManager();

        // 트랜잭션 얻어오고 실행한다.
        // JPA 는 트랜잭션 안에서 수행되어야 한다.
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        // exception 처리를 위해 try catch 문을 반드시 사용해야된다.
        try {
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);

            // 객체중심 설계
            RelationMember member = new RelationMember();
            member.setUsername("member1");
            member.setTeam(team);
            em.persist(member);

            // select 쿼리를 보고 싶을때
            em.flush(); // 영속성에있는 데이터를 DB 에 저장
            em.clear(); // 영속성 컨텍스트 모두 클리어
                        // 그래야 아래 에서 셀렉트 쿼리가 나간다.

            // 조회시 수정코드
            RelationMember findMember = em.find(RelationMember.class, member.getId());
            Team findTeam = findMember.getTeam();
            System.out.println("username: "+findMember.getUsername());

            // 수정
            // 변경만 하면 DB 값이 변경된다.
            Team newTeam = em.find(Team.class, 100L);
            findMember.setTeam(newTeam);

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

 

 

 

 

이점

  • 객체지향 설계를 할 수 있다.
  • 저장할 경우 setTeam 으로 팀객체를 바로 넣어주면된다.
  • 조회할 경우 멤버만 찾아서 바로 getTeam을 이용해 Team을 참조할수 있다.

 

 

 

 

 

 

 

참고: https://www.inflearn.com/course/ORM-JPA-Basic

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 본 강의는 자바 백엔

www.inflearn.com

 

 

728x90
반응형

댓글