https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
Inflearn의 김영한 강사님 강의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 을 보고 정리했습니다.
시나리오
Member에서 Team을 얻을 수 있지만Team에서 Member를 얻을 수는 없다.Member와 Team 양쪽으로 참조하여 서로를 얻을 수 있다.Member는 Team을 갖고 있지만 Team은 Member를 갖고있지 않다.Member와 Team 모두 연관관계를 설정해야 한다.public class Team {
...
@OneToMany(mappedBy = "team") // mappedBy : team에 의해서 관리가 된다. 읽기만 가능. 값을 넣어도 아무일도 벌어지지 않는다.
private List<Member> members = new ArrayList<>(); // ArrayList로 초기화 하는것이 관계, add할때 nullpoint가 안뜬다.
}
@Entity
public class Member {
...
@ManyToOne // 다대일 관계에서 멤버가 '다' 팀이 '일'
@JoinColumn(name = "TEAM_ID") // Team 객체와 TEAM_ID 외래키와 연관관계 매핑.
private Team team;
}
Member findMember = em.find(Member.class, member.getId()); List<Member> members = findMember.getTeam().getMembers(); // 멤버에서 팀으로, 팀에서 멤버로 접근이 된다.객체와 테이블간에 연관관계를 맺는 차이
Member 테이블의 외래키는 누구와 연결해야 하는가.Member의 팀을 바꾸고 싶을 때, Member의 Team을 바꿔야 할지 Team의 members를 바꿔야 할지 정해야한다.Member 혹은 Team 둘 중 하나로 외래키를 관리해야 한다.양방향 매핑 규칙
연관관계의 주인에 값을 입력하지 않음.
Member테이블에 Team이 저장되지 않는다.Team은 연관관계의 주인이 아니기 때문에 변경이 되지 않음.team.getMembers().add(member); 대신 member.setTeam(team); 을 해야 DB에 정상적으로 값이 들어간다.Team과 Member모두 값을 설정하는게 좋다.Team team = new Team(); em.persist(team); Member member = new Member(); member.setTeam(team); em.persist(member); Team findTeam = em.find(Team.class, team.getId()); // 영속성 컨텍스트 1차 캐시에 있는 내용을 꺼내온다 List<member> members = findTeam.getMembers(); //1차 캐시의 team에는 멤버가 없는상태로 들어와 있기 때문에 아무것도 가져오지 못한다.Member member = new Member(); em.persist(member); Team team = new Team(); team.getMembers().add(member); // 역방향(주인이 아닌 방향)만 연관관계 설정 em.persist(team);
연관관계 편의 메소드를 생성한다. (실수를 줄이기 위해)
@Entity public class Member { ... public void setTeam(Team team) { this.team = team; team.getMembers().add(this); // member에 team을 설정하면서 동시에 team에서도 member를 추가한다. } // set대신 로직을 쓰는것을 권장. public void changeTeam(Team team) { ... } }
양방향 매핑시에 무한 루프를 조심한다.
@Entity
public class Member {
...
@Override
public String toString() {
return ... + team + ... // team의 toString()이 호출된다.
}
}
@Entity
public class Team {
...
@Override
public String toString() {
return ... + members + ... // members의 컬렉션 하나하나의 toString() 들을 호출한다.
}
}
member의 toString()을 호출하면 team의 toString()이 호출되고 team의 toString()에서 member의 toString()을 호출하는 무한 루프가 생긴다.ex) toString(), lombok, JSON 생성 라이브러리.