연관관계와 주인설정

박준수·2023년 3월 5일
0

[JPA]

목록 보기
7/14
post-custom-banner

단방향 연관관계

@Entity
public class Member {

@Id @GeneratedValue
private Long id;

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

private int age;

//@Column(name = "TEAM_ID")
//private Long teamId;

@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;

//팀 저장Team team = new Team();

team.setName("TeamA");
 em.persist(team);



//회원 저장Member member = new Member();
 member.setName("member1");

member.setTeam(team); //단방향 연관관계 설정, 참조 저장
 
em.persist(member);//조회Member findMember = em.find(Member.class, member.getId());
//참조를 사용해서 연관관계 조회Team findTeam = findMember.getTeam();// 새로운 팀BTeam teamB = new Team();
 teamB.setName("TeamB");
 em.persist(teamB);// 회원1에 새로운 팀B 설정
 
member.setTeam(teamB);

양방향 연관관계와 연관관계의 주인

@Entitypublic class Team {
	private String name;

	@Id @GeneratedValueprivate Long id;@OneToMany(mappedBy = "team")List<Member> members = new ArrayList<Member>();

Team 엔티티에 List<Member> 컬렉션만 추가해주면 됨

테이블에 양방향 연관관계는 FK 하나로만 설정할 수 있다. 그러나 객체에서의 양방향 연관관계는 서로다른 단방향 관계를 두 개 설정한다고 생각하면 된다.

  • 회원 -> 팀 연관관계 1개(단방향)
  • 팀 -> 회원 연관관계 1개(단방향)

Member엔티티는 MEMBER테이블의 TEAM_ID(FK)와 연관관계 매핑이 되어 있고 Team 엔티티는 MEMBER 테이블에서 members 연관관계 매핑이 되어있다. 그렇다면 두 엔티티중 어떤 것이 MEMBER 테이블의 FK를 관리해야할까?

외래 키가 있는 곳을 주인으로 정해야 한다!!!

  • 연관관계의 주인만이 외래키를 등록, 수정
  • 주인이 아닌쪽은 읽기만 가능
  • 주인은 mappedBy속성 사용 X
  • 주인이 아니면 mappedBy 속성으로 주인을 지정

주의점

질문 : em.persis를 하면 영속성 컨텍스트의 1차 캐시에 저장이된다. em.flush(), em.clear()를 하지 않아도 em.find를 하면 1차 캐시에서 조회를 할 수 있다. 따라서 findteam을 얻어 findteam.getName()은 잘 출력이 된다. 그러나 findmember.getTeam().getMembers()로 members리스트를 가져올려면 무조건 em.flush()와 em.clear()를 해야지 다음 for문의 sout문이 출력이 된다. 그렇다면 findmember.getTeam().getMembers()는 1차 캐시에서 가져 올수 없어 db에서 가져와야 한다는 것인데 왜 1차 캐시에서 못가져오는 건지 잘 모르겠다.

답변 : em.flush(), em.clear()를 안 하게 되면 영속성 컨텍스트 안에서는 team과 member를 세팅한 저 상태 그대로 들어가 있다. 즉 findteam.getMembers()(=findmember.getTeam.getMembers)를 해도 1차 캐시에는 아무것도 들어 있지 않기에 for문에서는 멤버들을 조회할 수 없는 것이다.

따라서 순수한 객체 관계를 고려하면 항상 양쪽다 값을 입력해야 한다.


다음과 같이 member객체에 tream을 넣을 때 member뿐만아니라 team.getMembers.add(this)를 통해 양쪽 다 값을 넣을 수 있다.

정리

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것 뿐
  • JPQL에서 역방향으로 탐색할 일이 많음
  • 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨
 (테이블에 영향을 주지 않음)
profile
방구석개발자
post-custom-banner

0개의 댓글