똘이의 개발 Life

[ 자바 ORM 표준 JPA 프로그래밍 기본편 ] 세션 5 연관 관계 맵핑 기초 본문

Back-End/JPA

[ 자바 ORM 표준 JPA 프로그래밍 기본편 ] 세션 5 연관 관계 맵핑 기초

또리또리똘 2024. 1. 9. 14:18
728x90

 

참고 강의 

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

 

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

저는 야생형이 아니라 학자형인가봐요^^ 활용편 넘어갔다 30% 정도 듣고 도저히 답답해서 기본편을 들어버렸네요^^. 한주 한주 김영한님 강의 들으니 렙업되는 모습을 스스로 느낍니다. 특히 실

www.inflearn.com

 

RDB ( 관계형 데이터 베이스 ) 

- 외래키를 통한 다른 테이블 참조 

- 방향이 존재하지 않음.

- FK 를 통하면 양방향으로 연관관계 조회 가능

 

객체 

- 객체를 통한 다른 객체에 대한 데이터 참조 

- 양방향 객체 연관 관계를 위해서는 데이터 세팅이 필요함.

 


@Entity
public class Team{

	@Id @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    private STring name;
    
    // = new ArrayList<>() <- 값이 없을 때 Null 값이 되는 것을 방지 하기 위한 코드
    // OneTo Many 본인 객체에서 반대에 연결된 변수를 선언
    @OneToMany( mappedBy = "team" )
    private List<Member> members = new ArrayList<>(); 
   
   
    ...

}

 

mappedBy <- JPA 의 멘탈 붕괴 난이도 ( C 의 포인터 같은 존재 ) 

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

 

객체 연관 관계  = 2개

- 회원 -> 팀 연관관계 1개 

- 팀 -> 회원 연관관계 1개

 

단방향 연관 관계가 두 개가 있다. 

 

테이블 연관 관계 = 1개

- FK 값 

 

외래키 하나로 연관 관계가 해결이 된다.

 

객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계가 2개다.

 

테이블의 양방향 연관관계는 FK ( 외래키 ) 값 하나로 양방향 연관 관계를 갖는다.

 

우리는 객체지향 언어로 application 을 개발하지만 관계형 데이터 베이스의 기조를 무시할 수 없다. 

그렇기 때문에 관계형 데이터 베이스에 외래키에 대한 처치가 필요하다.

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

- 양방향 맵핑 규칙

- 객체의 두 관계중 하나를 연관관계의 주인으로 지정

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

- 주인이 아닌 쪽은 읽기만 가능

- 주인은 mappedBy 속성 사용 X 

- 주인이 아니면 mappedBy로 주인 지정 필요 

 

mappedBy 된 곳은 조회만 가능 / 반대편은 등록 수정 가능 

 

누구를 주인으로 ? 

외래 키가 있는 곳을 주인으로 정해라 

여기서는 Member.team 이 연관 관계의 주인 

연관 관계 주인 개념에 대한 도식

 

DB 입장에서는 1:N 일 때 N 쪽이 외래키를 갖고 있고 그렇기 때문에 N  쪽이 연관관계의 주인이 될 것 이다.

 

 주인 개념은 비지니스 로직에 관련된 범위가 아니다. 

JPA 기반 시스템 개발에 관한 개념이기 때문인 것을 인지해야 한다.

 

예시 ) 

Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 Member member = new Member();
 member.setName("member1");
 //역방향(주인이 아닌 방향)만 연관관계 설정
 team.getMembers().add(member);
 em.persist(member)

 

 

 

위와 같이 코드를 작성할 경우 insert 쿼리는 두 개가 날라가는 것을 볼 수 있다. 

team 테이블 , member 테이블에 데이터는 들어가나 member table 에 team_id 가 null 것을 확인할 수 있다. 

그 이유는 연관관계의 주인이 team객체에 선언되어 있기 때문이다. 

값을 삽입 및 수정하기 위해서는 연관 관계의 주인에 값을 설정 해야한다.

team 에 있는 member 리스트 객체는 읽기 전용이고 수정 및 삽입을 할 수 없다.

 

Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 Member member = new Member();
 member.setName("member1");
 
 //연관관계의 주인에 값 설정
 member.setTeam(team); //**
 em.persist(member)

 

 

하지만 여기 객체 지향스럽게 개발하는 방법이 있다. 

Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 
 Member member = new Member();
 member.setName("member1");
 member.setTeam(team); //**
 //연관관계의 주인에 값 설정
 // em.persist(member); <- 이렇게 될 경우 코드를 두 줄 작성해야한다.
 // 아래 setTeam 을 사용한다면 해결할 수 있다. 
 
 team.getMembers().add(member);
 
 // 위에 setTeam 에서 문제를 해결할 수 있다. 
 
 
 @Entity
 public class Member{
 	
    
    
    ...
    
 	public void setTeam( Team team ) {
            this.team = team;
            // this 는 나 자신의 인스턴스
            team.getMembers().add(this);
 	}
 
 }

 

양쪽에 모든 값을 넣어주는 방식으로 개발하면 장점이 있다. 

1. 주인관계에 있는 객체에만 값을 주입하고 영속성을 부여하면 DB에 들어가지 않는 이상 member list 객체에 값을 가져올 수 없다. 반면에 위와 같이 개발할 경우 양 쪽에서 데이터를 가져올 수 있다.

2. 테스트 케이스 작성 시 불편한 점을 해소해 준다.

 

양쪽 값 설정 시 주의해야할 점

- 연관 관계 편의 메소드 생성이 필요 ( 위의 setTeam 코드 참고 )

- 양방향 맵핑 시 무한 루프를 조심 

ex) toString() , lombok , JSON 라이브러리

- lombok에서 toString() 사용 하지 말기 

- JSON 같은 경우에는 controller 에는 entity 반환하지말고 DTO를 생성하여 반환하자.

 


 

 

아래 테이블 요구 사항이 있고 테이블 설계를 하려고 한다. 

 

우리는 우선 순위를 아래와 같이 생각할 수 있다. 

 

1. 단방향 관계를 우선 정의한다. 

2. application 개발을 진행한다. 

3. 양방향 관계가 필요할 경우 추가 개발한다. 

 

1. 단방향 관계를 우선 정의한다. 

단방향 관계는 FK 를 기준으로 정의한다. 

MEMBER 테이블과 ORDERS 테이블을 봤을 때 ORDERS 테이블에 MEMBER_ID ( FK , 외래키 ) 가 있음으로 

ORDERS Entity 에 단뱡항 정의를 해준다. 

@Entity
@Table(name="ORDERS")
public class Orders {


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


    @ManyToOne
    @JoinColumn( name = "MEMBER_ID")
    private Member member;

    private LocalDateTime orderDate;
    @Enumerated( EnumType.STRING )
    private OrderStatus status;

}

 

위와 같이 OrderItem 객체도 세팅을 하면 된다. 

 

2. application 개발 후 양방향 관계를 선언할지 판단.

위 조건에서는 OrderItem - Orders 에서 양방향 관계가 필요할 것이다. .

 

3. 양방향 관계가 필요한 경우 개발 

 

728x90

'Back-End > JPA' 카테고리의 다른 글

JPA org.hibernate.mapping.Value.getSelectables() value is null  (0) 2024.01.23