백엔드 개발자 - 젤리곰 2024. 6. 13. 17:35
728x90

1. 객체를 테이블에 맞춰 데이터 중심으로 모델링 했을 때

이 방식으로 모델링을 하면 객체지향과 거리가 멀어진다. 

왜 객체의 참조와 외래키를 매핑해야되는지 예시를 보며 이해해보자.

 

Member와 Team은 N:1 관계라고 하자.

 

✅Member

package hellojpa;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;


@Entity
@Getter
@Setter
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;

}

 

✅Team

package hellojpa;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Team {

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

 

✅Main() 실행부

package hellojpa;

import jakarta.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); //TEAM_ID값이 자동생성

//Member 객체 테이블에 추가
            Member member = new Member();
            member.setUsername("member1");
            //MEMBER테이블에 TEAM_ID값을 저장하려면 team에서 Id를 찾아와야함. 
            //외래키 식별자를 직접 다뤄야함.
            member.setTeamId(team.getId());
            em.persist(member);

//Member가 속한 Team이 무엇인지 조회
//Team을 바로 가져올 수 없음
//아래처럼 member의 teamId가 무엇이고 그 teamId에 해당하는 Team이 무엇인지, DB에 계속 확인해야됨.
            Member findMember = em.find(Member.class, member.getId()); 
            Long findTeamId = findMember.getTeamId();
            Team findTeam = em.find(Team.class, findTeamId); 

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

    }
}

 

💡 왜 객체의 참조와 외래키를 매핑해야할까? 

 

✔️ 데이터베이스에서는 외래 키와 JOIN을 사용하여 테이블 간의 관계를 정의하고 데이터를 조회한다.

SELECT * FROM member m
JOIN team t ON m.team_id = t.id

 

✔️ 객체 지향 프로그래밍에서는 객체가 다른 객체를 참조하여 관계를 정의한다.

public class Member {
    private Long id;
    private Team team; //다른 객체를 참조
    
    // getters and setters
}

public class Team {
    private Long id;
    private String name;
    
    // getters and setters
}

 

✔️ JPA를 사용할 때, 객체의 참조와 외래 키를 매핑을 해야 객체 지향 설계 원칙을 따르면서 데이터베이스와의 상호 작용을 원활하게 할 수 있다.

 

 

2. 객체의 참조와 외래키를 매핑했을 때

객체지향적으로 JPA를 사용하는 법을 코드로 보자.

 

✅Member

package hellojpa;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;


@Entity
@Getter
@Setter
public class Member {

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

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

    @ManyToOne //Member와 Team은 N:1
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}

 

 

 

데이터 중심 모델링 코드와 달리 TEAM_ID를 세팅하지않고 Team 객체를 참조한다.

그리고 참조하는 객체와의 관계(@ManyToOne)와 어떤 컬럼을 조인해서 가져올지(@JoinColum) 명시해주면 된다.

 

✅Team

데이터 중심 모델링 코드와 동일하다.

 

✅Main() 실행부 

package hellojpa;

import jakarta.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("member1");
            member.setTeam(team);//member.setTeamId(team.getId()); 이렇게 외래키 식별자를 직접 다룰 필요가 없다.

            em.persist(member);

            //Member가 속한 Team 조회하기
            Member findMember = em.find(Member.class, member.getId());
            Team findTeam = findMember.getTeam();
            
            //이전 코드는 Member에서 teamId를 찾고 이 teamId로 다시 Team을 찾아야했다.
            //이제 이런 코드가 필요없고 Team객체를 참조해서 getTeam을 하면 끝
            //Long findTeamId = findMember.getTeamId();
            //Team findTeam = em.find(Team.class, findTeamId); 
            
            
            System.out.println("findTeam = " + findTeam.getName());

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

    }
}

 

객체 참조하지 않고 데이터 중심으로 모델링했을 때와 달리, 외래키 식별자를 하나하나 찾아와서 Team을 찾아내는 코드가 필요없어졌다.

이렇게 연관관계 매핑을 통해 객체지향적인 방식으로 JPA를 다룰 수 있다.

 

728x90