테이블 는 FK 를 가지고 서로 다른 테이블이 연관 관계를 맺는다.
객체 는 참조주소 를 통해 서로 다른 객체와 연관 관계를 맺는다.
테이블 는 JOIN 연산을 통해 연관관계 탐색을 한다.
객체 는 참조 를 이용해서 연관관계 탐색을 한다 .
테이블 은 연관 관계를 맺은 두 테이블은 양방향 관계 이다.
/* TEAM -> MEMBER */ SELECT * FROM MEMBER m INNER JOIN TEAM t ON m.team_id = t.id; /* MEMBER-> TEAM */ SELECT * FROM TEAM t INNER JOIN MEMBER m ON t.id = m.team_id;둘 중 어떤 테이블에서든지 외래키 하나만으로 조인하여 다른 테이블을 탐색할 수 있다.
객체는 기본적으로 단방향 관계 이다.
class ObjectA { Long id; ObjectB objB; // Team을 참조 } class ObjectB { Long id; ObjectA objA; // Member를 참조 }하지만 각 객체가 서로를 참조하고 있으면 양방향 관계 인것처럼 구성을 할 수는 있다. 하지만 어디까지나 이런 방식은 단방향 관계가 2개 설정되어있을 뿐, 진정한 의미의 양방향 관계가 아니다.
테이블과 객체간의 차이점을 간단히 알아보았으니 이제 한번 JPA를 활용해 테이블의 연관관계를 객체에 매핑시켜보자.
우선 테이블 MEMBER 와 TEAM 을 객체로 매핑시키자. 참고로 한 TEAM 에 여러명의 MEMBER 들이 있으므로 MEMBER 와 TEAM 의 경우 N:1 또는 다대일 관계 라 부른다.
MEMBER : TEAM = N : 1
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
//연관관계 매핑
@ManyToOne
@ JoinColumn (name="TEAM_ID")
private Team team;
//연관관계 설정
public void setTeam(Team team) {
this.team = team;
}
//Getter, Setter ...
}
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
//Getter, Setter ...
}
@ManyToOne
Member 는 다대일 관계에서 '다' 에 속한다.

@JoinColumn
MEMBER 테이블은 TEAM_ID 를 FK 로 가지고 있기때문에 이 관계를 매핑 해주기 위해 위와 같이 해당 필드에 어노테이션을 등록해준다.
[주의1] 이 경우 ID 생성 전략이 자동 생성 방식 이므로 id필드에
null대신 직접 값을 할당하면 자동으로INSERT쿼리가 생성 안 될 수 있다.
[주의2] JPA 에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야한다.
보시다시피 Member 는 Team 을 참조하고 있으므로 JPA는 연관관계를 파악한 다음 commit 할 때 자동으로 참조한 Team 의 식별자(TEAM_ID) 를 입력해주었다.
PK==2 인 멤버를 찾는 코드만 작성했을 뿐인데 JPA는 연관관계를 파악한 다음, 알아서 해당 member가 참조하고 있는 team 까지 JOIN 해서 가져왔다.
앞에서 설명했듯이 JPA는 update라는 메서드가 따로 없으며 dirty checking 을 통해서 커밋 시점에 JPA 가 알아서 변경사항을 찾은 다음 해당 값을 반영해준다.
또한 em.persist() 을 따로 호출하지 않아도 되는 이유는 em.find() 를 호출할때 알아서 영속성에 집어 넣기 때문이다.
DB에서 서로 외래키 제약조건이 걸린 테이블을 삭제할 경우 먼저 서로의 연관관계를 제거해준 다음이여야지만 테이블을 삭제할 수 있다.
JPA도 마찬가지로 엔티티를 삭제하기 위해서는 연관관계를 끊어줘야한다. 그러기 위해서는 먼저 참조하고 있는 주소를 NULL 로 바꿔줘야한다.

만일 연관관계를 제거하지 않고 커밋을 하게되면 아래와 같은 에러가 발생한다.
※ 쿼리는 생성이 되지만 DB에 반영은 되지 않는다 .
본 포스트는
김영한의 자바 ORM 표준 JPA프로그래밍 기본 강의 및 도서를 참고하여 정리했습니다.