728x90

 

 

 

연관 관계 매핑이란 ❓

연관 관계 매핑객체 간의 관계를 데이터베이스의 관계로 어떻게 매핑할지를 정의하는 것입니다. 객체 지향 프로그래밍에서는 객체 간의 관계를 사용하여 현실 세계를 모델링하고, 이를 데이터베이스에 저장하려면 효과적인 방법이 필요합니다. JPA(Java Persistence API)는 이러한 연관 관계 매핑을 지원하며, 이를 통해 객체 모델과 데이터베이스 스키마를 매핑할 수 있습니다.

객체와 테이블 연관관계의 차이를 이해하고 객체의 참조와 테이블의 외래키를 매핑할 수 있습니다.

✍️ 연관 관계 매핑에서 사용되는 주요 용어

  1. 방향(Direction)
    • 연관 관계가 양방향인지 단방향인지를 나타냅니다.
    • 양방향 연관 관계는 서로를 참조하는 관계로, 한 객체가 다른 객체를 참조하고 동시에 다른 객체도 그 객체를 참조하는 관계를 말합니다. (예: 주문과 회원 간의 관계)
    • 단방향 연관 관계는 한 객체에서만 다른 객체를 참조하는 관계로, 한 쪽 방향으로만 참조가 가능합니다. (예: 주문과 배송 간의 관계)
  2. 다중성(Multiplicity)
    • 객체 간의 관계가 1:1, 1:N, N:1, N:N 등 얼마나 많은 객체가 연결되어 있는지를 나타냅니다.
    • 1:1은 한 객체가 다른 객체와 하나의 관계만 가지는 경우를 말합니다.
    • 1:N은 한 객체가 여러 개의 다른 객체와 관계를 가지는 경우를 말합니다.
    • N:1은 여러 개의 객체가 하나의 객체와 관계를 가지는 경우를 말합니다.
    • N:N은 여러 개의 객체가 여러 개의 다른 객체와 관계를 가지는 경우를 말합니다. (예: 주문과 상품 간의 관계)
  3. 연관 관계의 주인(Owner)
    • 양방향 연관 관계에서 관계를 주도하는 쪽을 연관 관계의 주인이라고 합니다.
    • 연관 관계의 주인은 데이터베이스에서 외래 키(Foreign Key)를 관리하며, 데이터베이스에 데이터를 저장하거나 수정할 때 주인 쪽의 변화가 반영됩니다.
    • 주인이 아닌 쪽은 읽기만 가능하고 데이터베이스에 영향을 주지 않습니다.

주의해야 할 점은 연관 관계의 주인은 데이터베이스의 관점에서 중요한 역할을 하며, 객체지향의 관점에서 중요하지 않을 수 있습니다. 때문에 연관 관계의 주인을 선택할 때는 데이터베이스의 특성과 운영을 고려하여 결정하는 것이 좋습니다.

이러한 방향, 다중성, 연관 관계의 주인 개념은 객체 간의 관계를 데이터베이스에 매핑할 때 혼란을 방지하고 일관된 관계를 구성하기 위해 중요한 역할을 합니다.

 

✅ 예제 시나리오

회원과 팀으로 구분지어 연관관계를 지어보도록 하겠습니다.

⭐ 회원은 하나의 팀에만 소속될 수 있습니다.
⭐ 회원과 팀은 다대일 (N:1)의 관계로 맺어집니다.

객체를 테이블에 맞춰 모델링을 한 경우 아래와 같은 ER 다이어그램이 그려집니다.

 

💥 테이블에 객체를 맞춘 데이터 중심 모델링

 

 
       public static void main(String[] args) {

                EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

                EntityManager em = emf.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();

                //외래 키 식별자를 직접 다루는 코드
                try {

                    //Team 저장 코드
                    Team team = new Team();
                    team.setName("TeamA");
                    em.persist(team);

                    //Member 저장코드
                    Member member = new Member();
                    member.setUsername("회원 1");
                    member.setTeamId(team.getId()); //회원 1을 TeamA에 소속시키고자 함
                    em.persist(member);


                    tx.commit();

                } catch (Exception e) {
                    e.printStackTrace();//추가
                    tx.rollback();
                }finally {
                    em.close();
                }

                emf.close();

                }

 

객체를 테이블에 맞추어 데이터 중심으로 모델링하면 협력 관계를 만들 수 엇습니다. 테이블은 외래 키로 조인을 사용해서 연관 테이블을 찾는 반면, 객체는 참조를 사용해서 연관된 객체를 찾는 큰 차이점이 존재합니다.

객체지향 프로그래밍에서는 객체 간의 관계가 더 복잡한 경우가 많습니다. 이를 데이터베이스에 매핑할 때에는 단순한 테이블 간의 관계만으로 표현하기 어려울 수 있습니다. 단방향 / 양방향 연관관계는 이러한 객체지향 모델을 데이터베이스 모델로 효과적으로 매핑하기 위해 사용됩니다.

 

단방향 연관관계

Team 객체를 Getter나 Setter로 호출하여 사용하는 것이 아닌 Team Entity 그 자체를 Member Entity와 연관 관계를 주어 사용하고자 합니다. JPA에게 관계를 지정해주어야 하며, 일 대 일 or 일 대 다인지가 중요한 부분입니다. Member의 관점에서는 Member가 N , Team이 1의 입장이기 때문에 @ManyToOne 어노테이션이 Member 테이블에 선언된 Team 클래스에 작성해야 합니다.

단방향 연관관계두 개의 객체 간의 관계를 나타내는데, 한 객체가 다른 객체를 참조하는 것입니다. 즉, 한 객체에서 다른 객체로의 관계를 설정하고 사용하는 것이지만, 반대 방향의 참조는 없는 상태를 의미합니다.

예를 들어, 팀(Team)과 팀원(Member)라는 두 개의 엔티티가 있다고 가정해보겠습니다. 여기서 팀원은 팀원을 참조하므로, 팀원 엔티티에 팀원의 정보를 저장하는 멤버 변수를 추가합니다. 이 때 팀원의 정보를 저장하기 위해 외래 키를 사용할 수 있습니다.

단방향 연관관계의 특징은 다음과 같습니다:

  1. 한 객체에서 다른 객체로의 참조만 존재하며, 그 반대는 성립하지 않습니다. 예를 들어, 팀에서 팀원을 참조할 수 있지만 작성자 객체에서 해당 작성글을 바로 참조하는 것은 어렵습니다.

  2. 객체의 참조를 통해 다른 객체를 조회하거나 조작할 수 있습니다. 위의 예에서 팀 객체에서 팀원을 조회하거나 수정할 수 있습니다.

  3. 데이터베이스 테이블 간의 관계로는 해당 연관관계를 한쪽 방향으로만 설정하면 됩니다. 즉, 팀의 테이블에 팀원 정보를 저장하는 컬럼을 추가하면 됩니다.

단방향 연관관계는 간단하고 명확한 구조를 가지고 있어 일반적인 상황에서 유용하게 활용됩니다. 하지만 객체지향 모델링의 관점에서는 한쪽 방향으로만 접근할 수 있는 구조이므로, 양방향 연관관계가 필요한 경우도 있을 수 있습니다.

 

💡 Team과 Member ⇒ @ManyToOne (member기준)

 

                public static void main(String[] args) {

                        생략..

                        //외래 키 식별자를 직접 다루는 코드
                        try {

                            //연관 관계 매핑 후 Team 저장 코드
                            Team team = new Team();
                            team.setName("TeamA");
                            em.persist(team);

                            //연관 관계 매핑 후 Member 저장코드
                            Member member = new Member();
                            member.setUsername("회원 1");
                            member.setTeam(team);
                            em.persist(member);

                            Member findMember = em.find(Member.class, member.getId());
                            Team findTeam = findMember.getTeam();

                            System.out.println("findTeam.getName = " + findTeam.getName());

                        생략..


                ============== 쿼리문 출력 결과=======================
                Hibernate: 
                    select
                        m1_0.MEMBER_ID,
                        t1_0.TEAM_id,
                        t1_0.name,
                        m1_0.USERNAME 
                    from
                        Member m1_0 
                    left join
                        Team t1_0 
                            on t1_0.TEAM_id=m1_0.TEAM_ID 
                    where
                        m1_0.MEMBER_ID=?

                System.out.println("findTeam.getName = " + findTeam.getName());
                findTeam.getName = TeamA
728x90
반응형

'[ BACKEND] > Spring' 카테고리의 다른 글

[SPRING] 다양한 연관관계의 종류  (0) 2023.08.11
[SPRING] 양방향 연관관계  (0) 2023.08.09
[SPRING] Entity Mapping (엔티티 매핑)  (0) 2023.08.07
[SPRING] Entity와 영속성  (0) 2023.08.06
[SPRING] ORM 그리고 JPA  (0) 2023.08.05

+ Recent posts