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 생성 라이브러리.