@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();
// 새로운 팀B
Team teamB = new Team();
teamB.setName("TeamB");
em.persist(teamB);
// 회원1에 새로운 팀B 설정
member.setTeam(teamB);
@Entity
public class Team {
private String name;
@Id @GeneratedValue
private 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에서 역방향으로 탐색할 일이 많음
- 단방향 매핑을 잘 하고 양방향은 필요할 때 추가해도 됨 (테이블에 영향을 주지 않음)