엔티티들은 대부분 다른 엔티티와 연관관계가 있다. 그런데 객체는 참조(주소)를 사용해서 관계를 맺고 테이블은 외래키를 사용해서 관계를 맺는다. 따라서 이번 장에서는 객체의 참조와 테이블의 외래키를 매핑하는 것을 목표로 한다.
객체 연관관계와 테이블 연관관계의 가장 큰 차이
참조를 통한 연관관계는 언제나 단방향이다. 객체간에 연관관계를 양방향으로 만들고 싶으면 반대쪽에도 필드를 추가해서 참조를 보관해야 한다. 결국 연관관계를 하나 더 만들어야 한다. 이렇게 양쪽에서 서로 참조하는 것을 양방향 연관관계라 한다. 하지만 정확히는 양방향 관계가 아니라 서로 다른 단방향 관계 2개다. 반면에 테이블은 외래키 하나로 양방향 조인을 할 수 있다.
public class Member {
private String id;
private String password;
private Team team; // Team 의 참조를 보관
public void setTeam(Team team) {
this.team = team;
}
...
}
public class Team {
private String id;
private String name;
...
}
CREATE TABLE MEMBER (
MEMBER_ID VARCHAR(255) NOT NULL,
TEAM_ID VARCHAR(255),
USERNAME VARCHAR(255),
PRIMARY KEY (MEMBER_ID
)
CREATE TABLE TEAM (
TEAM_ID VARCHAR(255) NOT NULL,
NAME VARCHAR(255),
PRIMARY KEY (TEAM_ID)
)
ALTER TABLE MEMBER ADD CONSTRAINT FK_MEMBER_TEAM
FOREIGN KEY (TEAM_ID)
REFERENCES TEAM
@Entity
public class Member {
@Id
@Column(name = "MEMBER_ID")
private String id;
private String username;
// 연관관계 매핑
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
// 연관관계 설정
public void setTeam(Team team) {
this.team = team;
}
...
}
@Entity
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
private String name;
...
}
@ManyToOne
: 회원과 팀은 다대일 관계이므로 다대일 관계를 매핑하기 위한 어노테이션이다. 연관관계를 매핑할 때 이렇게 다중성을 나타내는 어노테이션을 필수로 사용해야 한다.@JoinColumn(name="TEAM_ID")
: 조인 컬럼은 외래키를 매핑할 때 사용한다. name 속성에는 매핑할 외래키 이름을 지정한다. 이 어노테이션은 생략할 수 있다.
일대다 관계는 여러 건과 연관관계를 맺을 수 있으므로 컬렉션
을 사용해야 한다.
@Entity
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
private String name;
// 추가
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
...
}
mappedBy
속성은 양방향 매핑일 때 사용하는데 반대쪽 매핑의 필드 이름을 값으로 주면 된다. 반대쪽 매핑이 Member.team 이므로 team
을 값으로 주었다.