[강의 정리] 연관관계 매핑 기초 - 단방향

나무·2023년 12월 1일

JPA 

목록 보기
4/11
post-thumbnail

1. 테이블 연관관계 VS 객체 연관관계

연관 관계 맺기

테이블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개 설정되어있을 뿐, 진정한 의미의 양방향 관계가 아니다.



2. 객체 관계 매핑 - 단방향

테이블과 객체간의 차이점을 간단히 알아보았으니 이제 한번 JPA를 활용해 테이블의 연관관계를 객체에 매핑시켜보자.

우선 테이블 MEMBERTEAM 을 객체로 매핑시키자. 참고로 한 TEAM 에 여러명의 MEMBER 들이 있으므로 MEMBERTEAM 의 경우 N:1 또는 다대일 관계 라 부른다.

MEMBER : TEAM = N : 1

Member 엔티티

@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 ...
}

Team 엔티티

@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 에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야한다.

보시다시피 MemberTeam 을 참조하고 있으므로 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프로그래밍 기본 강의 및 도서를 참고하여 정리했습니다.

profile
🍀 개발을 통해 지속 가능한 미래를 만드는데 기여하고 싶습니다 🍀

0개의 댓글