inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

자바 ORM 표준 JPA 프로그래밍 - 기본편

단방향 연관관계

안녕하세요

473

작성자

작성한 질문수 57

0

이 부분에서 em.persist(team) 을 한 후 회원 저장 구현을 한 후 em.persist(member) 를 했는데 회원 구현 이후에 em.persist(team) 를 해도 되나요? 회원 저장 구현 전에 em.persist(team) 를 해야 하는 이유가 있나요?

jpa JPA java

답변 1

4

초보웹프로그래머

안녕하세요.

같은 강의를 듣고 공부하고 있는 지나가던 나그네 입니다.

제가 공부한 내용을 토대로 답변을 한 번 드려보려고 합니다.

 

말씀주신 질문을 토대로 테스트 코드를 아래처럼 작성해봤습니다.

@Test
@DisplayName("member - team 테스트")
void memberTeamTest() {
    Team team = new Team();
    team.setName("team1");
    em.persist(team);

    Member member = new Member();
    member.setName("member1");
    member.setTeam(team);
    em.persist(member);

    // 아래 flush 와 clear 는 실제 insert 쿼리를 확인해보기 위해 추가했습니다.
    em.flush();
    em.clear();
    
    assertThat(member.getId()).isNotNull();
}

 

먼저 아래처럼 em.persist(team) 만 em.persist(member) 아래로 내려도 실제 동작 수행에는 크게 문제가 되지 않습니다.

@Test
@DisplayName("member - team 테스트")
void memberTeamTest() {
    Team team = new Team();
    team.setName("team1");

    Member member = new Member();
    member.setName("member1");
    member.setTeam(team);

    em.persist(member);
    em.persist(team);

    // 아래 flush 와 clear 는 실제 insert 쿼리를 확인해보기 위해 추가했습니다.
    em.flush();
    em.clear();
    
    assertThat(member.getId()).isNotNull();
}

 

하지만, 실제로 테스트를 실행해보면 update 쿼리가 하나 더 실행되실 겁니다.

이유는 영속성 컨텍스트에 데이터가 생성되는 시점이 달라서 인데요.

em.persist 는 객체를 영속성 컨텍스트에 영속화 하게 되는데, member를 먼저 영속화 하는 경우,

team 객체가 영속화 되어있지 않은 상태이기 때문에, team 객체에 id가 없습니다.

영속성 컨텍스트 내 1차캐시 상황을 그려보면 아래와 같을 것으로 예상이 되는데요.

image자바 상에서 team 이라는 객체는 생성됐지만, EntityManager에 의해 영속화 되기 전이기 때문에 id 는 null로 들어가게 될 것으로 예상됩니다.

그 다음에 team 을 영속화 하게 되면 아래처럼 1차 캐시가 변경될 것 입니다.

image이 상태에서 member 객체 내에 있는 team 객체가 영속화가 되었으니, team id 가 생성되었으므로

member가 참조하는 team에도 해당 id를 부여할 것으로 예상됩니다. 따라서 아래처럼 다시 1차캐시가 바뀌게 될 것입니다. ( 같은 트랜잭션 내에서 발생되어 변경감지로 간주되는 것으로 예상됩니다.)

image이 경우 에서 1차캐시에 있는 내용을 DB에 반영하면 SQL이 순차적으로 아래 처럼 발생하게 됩니다.

  1. INSERT INTO member(id, name, member_id) VALUES(1, "member1", null);

  2. INSERT INTO team(id, name) VALUES(2, "team1");

  3. UPDATE member SET team_id = 2 WHERE id = 1;

image

즉, 연관관계가 맺어져 있는 entity를 insert 하는 경우, 외래키를 가지는 연관관계의 주인을 나중에 insert 해야 insert 쿼리 2개가 발생하고,

질문 주신대로 순서를 바꿔서 persist 하는 경우에는 결과적으로 반영되는 데이터는 동일할지라도update 쿼리가 한 번 더 발생해서 3번의 쿼리가 발생되게 됩니다.

 

쿼리 2번이면 될 작업을 굳이 쿼리 3번으로 할 필요는 없겠죠? 이러한 이유 때문에 team 을 먼저 persist 하고 member 를 나중에 persist 한 것으로 예상됩니다.

 

저도 JPA 를 공부하는 입장이라 신뢰성(?)은 다소 떨어질 수 있지만, 제가 공부한 내용과 실제 테스트코드를 돌려본 결과로 인해 도출된 결과를 답변드리니 공부하실 때 참고되셨으면 좋겠습니다.

(혹시 영한님께서 이 답변을 보신다면.... 제 답변에 잘못된 내용 지적해주시면 감사드리겠습니다...!)

벌크연산에서 member.getAge 호출 시 영속성 컨텍스트에서 데이터를 가져오는건가요?

0

29

2

inheritance startegy 선택시 고려사항

0

22

1

Entity 동등성 비교

0

21

1

실무 조언 관련 질문입니다.

0

47

1

H2데이터베이스 파일 생성

0

56

2

서브쿼리 강의에서 ALL 예시 관련 질문드립니다.

0

53

2

수정또는 삭제시 영속성 엔티티에 값이 무조건 있어야 하나요?

0

55

1

JPQL 메소드와 락

0

55

1

Delivery @OneToOne

0

60

1

17강 4~5분대 테이블 값 조회가 안됩니다.

0

94

2

UnsupportedOperationException 발생

0

86

3

H2 Database 연결이 안됩니다.

0

95

2

연관관계 매핑 질문드립니다.

0

85

2

h2데이터베이스 실행오류

0

108

2

persistence.xml

0

108

2

양방향 연관관계에서 연관관계의 주인(mappedBy)을 왜 꼭 정해야 하나요?

0

80

1

영속성 컨텍스트

0

66

1

JPA 프록시

0

97

1

Native Query와 MyBatis

0

70

1

영속성 컨텍스트는 어떤 메모리에 저장되는건가요?

0

87

1

임베디드 타입 예시 코드 관련 질문

0

115

3

명시적 조인에서 별칭을 주면 왜 객체에 접근할 수 있나요

0

95

3

인텔리제이 패키지 커서 단축키 질문

0

108

2

혹시 현재는 ID 데이터 타입이 String이면 안되나요?

0

145

1