양방향 매핑의 필요성

김민지·2022년 10월 19일
0

JPA

목록 보기
6/27
post-custom-banner

예제를 풀다가..

https://www.blog.ecsimsw.com/m/entry/JPA-%EC%98%81%EC%86%8D%EC%84%B1-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-1%EC%B0%A8-%EC%BA%90%EC%8B%9C-%EC%93%B0%EA%B8%B0-%EC%A7%80%EC%97%B0

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

Team teamA = new Team();
teamA.setName("TeamA"); 
em.persist(teamA); // 1차캐시에 저장

Member member_A = new Member();
member_A.setName("memberA"); 
member_A.setTeam(teamA);
em.persist(member_A); // 1차 캐시에 저장

Member findMember = em.find(Member.class, member_A.getId()); // 1차 캐시에서 얻어옴
Team findTeam= findMember.getTeam(); // 1차캐시에서 얻어온것

System.out.println(findTeam.getMembers().size());  // 0

tx.commit();
  • 위의 코드는 양방향 매핑을 잘 해주지 않았기 때문에(team.setMember를 해주지 않아서) 1차캐시에 애초에 findTeam.getMembers가 없다. 그래서 size=0이 나온것
    하지만 저렇게 단방향으로만 매핑을 해주어도 서로 참조가 가능하긴하다. 그래서 아래와 같이 flush,clear를 넣어주면
    자동으로 넣어준다
@Test
	@Transactional
	void contextLoads() {
		Member member = Member.builder().name("김길동").build();
		em.persist(member);//1차 캐시에 저장
		Team team = Team.builder().name("이름이").build();
		em.persist(team);//1차 캐시에 저장
		team.settingMember(member);//양방향으로 setting해주는 건 아니고 member만 team에 넣어줬다
		Member findMember = em.find(Member.class, member.getId());
		em.flush();//디비랑 동일해지도록 1차캐시내용을 디비로 전송한다
		em.clear();
		Team findTeam = em.find(Team.class, team.getId());//그래도 1차캐시에는 아직 setting되지 않았을테니 내용이 남아있다
		//인스턴스의 내용은 다르다. 왜냐하면 디비에 내용보내서 얻어온 거일테니 냐용이 다르겠지
		Assertions.assertEquals(findMember.getName(), findTeam.getMemberList().get(0).getName());
		Assertions.assertEquals(findTeam.getName(), findMember.getTeam().getName());
	}

인스턴스의 내용이 다른 이유

Assertions.assertEquals(findMember, findTeam.getMemberList().get(0));
양방향 참조를 해줬는데도 왜 인스턴스의 내용이 다를까?

  • clear해주고 조회를하면 db에서 요청받아서 저장하니까 참조값이 달라지게 된다
profile
안녕하세요!
post-custom-banner

0개의 댓글