JPA 연관 관계

특징

데이터베이스 외래 키 하나로 두 테이블이 관계를 맺는다.

엔티티는 양방향으로 연관 관계를 맺으면 연관 관계를 관리하는 포인트는 2곳이 된다.

필수 지식

@JoinColumn

외래 키(FK)를 매핑할 때 사용된다.

name; 매핑할 외래 키 이름; default 필드명 + _ + 참조하는 테이블의 PK 컬럼명

아래와 같이 회원 Entity를 선언하고 팀 Entity과 연관 관계를 맺었는데, @JoinColumn만 선언하고 name 필드 값을 선언 하지 않으면 team_TEAM_ID로 선언된 외래 키(FK)를 찾고 매핑한다.

public class Member {
	@Id
	@Column(name = "user_id")
	private String id;
	
	private String name;
	
	@ManyToOne
	@JoinColumn
	private Team team;
}

public class Team {
	@Id
	@Column(name = "team_id")
	private UUID id;
	
	@Column(name = "team_name")
	private String name;	
}

연관 관계 매핑

객체 연관 관계; 회원 객체의 Memeber.team 필드 사용

테이블 연관 관계; 회원 테이블의 MEMBER.TEAM_ID 외래 키 컬럼 사용

Member.team과 MEMBER.TEAM_ID를 매핑하는 것이 연관관계 매핑이다.

연관 관계를 사용한 등록(Create)/조회(Read)/수정(Update)/삭제(Delete)

Create

팀 엔티티를 저장하고 회원 엔티티가 팀 엔티티의 Team.id(FK)를 참조하고 저장했다. JPA는 참조한 팀의 식별자(Team.id)를 외래 키로 사용해서 적절한 Insert Query를 생성한다.


Team team = new Team();
team.setId("1234-1234-1234-1234");
team.setName("Order Of The Phoenix");

em.persist(team);

Member m1 = new Member();
m1.setId("SB");
m1.setName("Sirius Black");
m1.setTeam(team); // Memeber가 Team을 참조했다.

em.persist(m1);

다대일 [N:1]

임직원은 팀에 속하며, 팀은 임직원으로 구성되어 있다.

단방향

스크린샷 2025-01-14 오후 9.50.50.png

@JoinColumn(name = "TEAM_ID")를 이용해서 Employee.team 필드를 employee 테이블의 TEAM_ID 외래 키(FK) 컬럼과 매핑했다. 따라서 Employee.team 필드로 employee 테이블의 TEAM_ID 외래 키를 관리한다.

@Entity
public class Employee {
	@Id
	private String id;
	
	@ManyToOne
	@JoinColumn(name = "team_id")
	private Team team;
}

@Entity
public class Team {
	@Id
	private String id;
	
	private String teamName;
}

양방향

스크린샷 2025-01-14 오후 9.51.16.png

실선이 연관 관계의 주인(Employee.team)이고 점선(Team.members)은 연관 관계의 주인이 아니다.

@Entity
public class Employee {
	@Id
	private String id;
	
	@ManyToOne
	@JoinColumn(name = "team_id")
	private Team team;
}

@Entity
public class Team {
	@Id
	private String id;
	
	private String teamName;
	
	@OneToMany(mappedBy = "team")
	List<Employee> members;
}

일대다 [1:N]

팀은 여러 명의 임직원을 가진다.

단방향

Team.emplyeese로 emplyee 테이블의 team_id 외래 키를 관리한다. 보통 자신이 매핑한 테이블(team)에 외래 키가 있고 해당하는 외래 키를 관리하는데, 이 매핑은 반대쪽 테이블(emplyee)에 있는 외래 키를 관리한다. 그럴 수 밖에 없는 것이 일대다 관계에서는 외래 키가 항상! 다(N)쪽 테이블에 있다.

일대다 단방향 매핑에서는 꼭! @JoinColumn를 명시 해줘야 한다. 그렇지 않다면, JPA가 자동으로 연관 관계를 관리하는 JOIN 테이블 전략을 기본적으로 사용해서 매핑한다.

스크린샷 2025-01-15 오후 1.40.45.png

public class Team {
	@Id
	@Column(name = "team_id")
	private UUID id;
	
	@OneToMany
	@JoinColumn(name = "team_id")
	List<Employee> employeese;	
}

public class Employee {
	@Id
	@Column(name = "user_id")
	private String id;
	
	private String password;
}
Employee a = new Employee();
Employee b = new Employee();

Team dataplatform = new Team();
// Setter를 이용해서 필요한 모든 값을 할당 했다고 가정
employeeRepository.save(a); // INSERT a
employeeRepository.save(b); // INSERT b
teamRepository.save(dataplatform); // INSERT dataplatform and UPDATE a.team_id

일대다 관계에서는 외래 키(FK)가 자신의 테이블이 아닌 다른 테이블에 있다는 점이다. 본인 테이블에 외래 키가 있으면 Entity의 저장과 연관 관계 처리를 Insert Query 한번으로 끝낼 수 있지만, 다른 테이블에 외래 키가 있으면 연관관계 처리를 위한 UPDATE 쿼리를 추가 실행해야 한다는 단점을 가진다.

일대일 [1:1]

양쪽이 서로 하나의 관계만 가진다. 예를 들어 회원은 하나의 장바구니를 부여 받고 사용하고 하나의 장바구니도 하나의 회원에 속해진다.

특징

일대일 관계는 그 반대로 일대일 관계이다.