본문 바로가기
JPA/JPA

[JPA] 다양한 연관관계 매핑 - 다대다

by yoon_seon 2023. 4. 14.

다대다 [N:M]

실무에서는 사용하면 안된다.

관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.

연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야한다.

객체는 컬렉션을 사용해서 객체 2개로 다대다 관계를 만들 수 있다.

그래서 JPA는 연결 테이블을 매핑 시키는 기능을 지원해준다.

 

다대다 단방향

@Entity
@Getter @Setter
public class Member {
	@Id @GeneratedValue
	private Long id;
	
	@Column(name = "USERNAME")
	private String username;
	
	@ManyToOne
	@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
	private Team team;
	
	@OneToOne
	@JoinColumn(name="LOCKER_ID")
	private Locker locker;
	
	@ManyToMany
	@JoinTable(name = "MEMBER_PRODUCT")
	private List<Product> products = new ArrayList<>();
}

@Entity
@Getter @Setter
public class Product {
	@Id @GeneratedValue
	private Long id;
	
	private String name; 
}

Member에 @ManyToMany를 적용해 다대다 관계를 설정, @JoinTable 어노테이션으로 중간 테이블 생성한다.

  • @JoinTable(name ="MEMBER_PRODUCT") : MEMBER_PRODUCT라는 두 객체의 테이블의 외래 키만 저장하는 중간 테이블을 생성하고 Member와 Product 테이블에 외래키를 제약조건을 설정해준다. 

 

다대다 양방향

@Entity
@Getter @Setter
public class Member {
	@Id @GeneratedValue
	private Long id;
	
	@Column(name = "USERNAME")
	private String username;
	
	@ManyToOne
	@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
	private Team team;
	
	@OneToOne
	@JoinColumn(name="LOCKER_ID")
	private Locker locker;
	
	@ManyToMany
	@JoinTable(name = "MEMBER_PRODUCT")
	private List<Product> products = new ArrayList<>();
}

@Entity
@Getter @Setter
public class Product {
	@Id @GeneratedValue
	private Long id;
	
	private String name;
	
	@ManyToMany(mappedBy = "products")
	private List<MemberR> members = new ArrayList<>();
}

Product에 @ManyToMany 및 mappedBy로 연관관계를 설정해준다.

@OneToOne과 동일하지만 두 객체의 테이블의 외래 키만 저장하는 중간 테이블을 만들어준다는 차이가 있다.

 

 

다대다 매핑의 한계

연결 테이블은 단순히 연결만 하고 끝나지 않는다.

두 객체의 테이블의 외래 키만 저장하기 때문에 추후 다른 저장할 데이터가 추가되어 컬럼이 추가 된다면  중간 테이블에 추가 컬럼을 넣을 방법이 없다.

또, 중간테이블이 숨겨져 있기 때문에  자기도 모르는 복잡한 조인 쿼리가 발생하는 경우가 생길 수 있다.

그래서 편리해 보이지만 실무에서 사용하지 않는다.

 

 

다대다 한계 극복

연결 테이블용 엔티티를 추가(연결 테이블을 엔티티로 승격)

@Entity
public class MemberProdect {
	@Id @GeneratedValue
	private Long id;
	
	@ManyToOne
	@JoinColumn(name = "MEMBER_ID")
	private MemberR member;
	
	@ManyToOne
	@JoinColumn(name = "PRODECT_ID")
	private Product product;	
}

@Entity
@Getter @Setter
public class Product {
	//...
	
	@OneToMany(mappedBy = "product")
	private List<MemberProdect> members = new ArrayList<>();
}

@Entity
@Getter @Setter
public class Member {
	//...
	
	@OneToMany(mappedBy = "member")
	private List<MemberProdect> memberProdects = new ArrayList<>();
}

이런식으로 MemberProdect 엔티티를 생성하고 일대다, 다대일 관계로 풀어낸다면 추후 추가되는 컬럼을 넣을 수 있다.

 

 

 

 


해당 글은 인프런의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 강의를 정리한 내용입니다.

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

댓글