Direction
): 단방향, 양방향Multiplicity
): 다대일(N:1
), 일대다(1:N
), 일대일(1:1
), 다대다(N:M
)Owner
): 객체 양방향 연관관계는 관리 주인이 필요@Entity
public class Member {
@Id
private Long id;
@Column(name = "USERNAME")
private String name;
@Column(name = "TEAM_ID")
private Long teamId;
}
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
}
//조회
Member findMember = em.find(Member.class, member.getId());
//연관관계가 없음
Team findTeam = em.find(Team.class, team.getId());
테이블 : 외래키 조인
vs
객체 : 참조
객체 그래프 탐색
: 객체
는 참조
를 사용해 연관관계를 탐색조인
: DB
는 외래 키
를 사용해 연관관계를 탐색@Entity
public class Member {
@Id
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
@JoinColumn(name = "TEAM_ID")
외래 키
를 매핑할 때 사용한다.name
속성에는 매핑할 외래 키
이름을 지정한다.TEAM_ID
외래 키로 연관관계를 맺으므로 이 값을 지정하면 된다.필드명
+ _
+ 참조하는 테이블의 기본 키 컬럼명
team_TEAM_ID
public class MainJPA {
public static void main(String[] args) {
//팀 저장
Team team = new Team("TeamA");
em.persist(team);
//회원 저장
Member member = new Member("member1", team); //단방향 연관관계 설정, 참조 저장
em.persist(member);
//조회
Long id = member.getId();
Member findMember = em.find(Member.class, id);
//참조를 사용해서 연관관계 조회
Team findTeam = findMember.getTeam();
// 새로운 팀B
Team teamB = new Team("TeamB");
em.persist(teamB);
// 회원1에 새로운 팀B 설정
member.setTeam(teamB);
}
}
@Entity
public class Member {
@Id
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<Member>();
}
@OneToMany(mappedBy = "team")
- 객체 : 사실 2개의 단방향 연관관계
- 테이블 : PK, FK를 통해 양방향 연관관계
Member 객체 자체와 테이블 매핑 vs Team 속 members 리스트를 통해 테이블 매핑
- 만약
Member
객체는 그대로 인데members
리스트는 빈 리스트이면???- 둘중 뭐로 매핑할지 정해야 함
Owner
)위의 두 관계 중 하나만 연관관계 주인으로 설정
외래키가 있는 쪽이 주인!!!(team)
n 쪽
주인의 반대편, PK 있는 쪽(members)
1 쪽
mappedBy
속성 사용!@OneToMany(mappedBy = "team")
class Main {
public static void main(String[] args) {
Team team = new Team("TeamA");
em.persist(team);
// 1. 역방향(주인이 아닌 방향)만 연관관계 설정
Member member = new Member("member1");
team.getMembers().add(member);
em.persist(member);
// 오류!!!
// 2. 연관관계 주인 방향도 값 설정
Member member = new Member("member1", team);
team.getMembers().add(member);
em.persist(member);
// 정상 작동!!!
}
}
주인값
, 비 주인값
(리스트) 꼭 입력해야 함항상 양쪽에 값을 설정
하자!@Entity
public class Member {
//...
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);// !!!!
}
}
Team.addMembers(team)
형태로 만들기도 함연관관계 변경 시
기존 연관관계가 있으면, 해당 관계를 삭제하는 코드를 추가해야 함!!toString()
member{team{member{team{...}}}}
JSON
변환시 자주 발생JSON 관련 라이브러리
에서 제공하는 어노테이션
/기능
을 써 해결 가능lombok
에서는 toString()
쓰지마라!entity
를 반환하는 대신 DTO
를 사용해라[책, 강의]
자바 ORM 표준 JPA 프로그래밍
(김영한
)