[N:N 관계]
N:N 테이블의 관계에서는 <중간 객체>를 생성하여 1:N, N:1 관계로 만든다.
<중간 객체>는 양쪽의 객체를 FK로 가지고 있다.
1. N:1 관계 먼저 매핑
N클래스
@ManyToOne : N클래스에서 1클래스 객체를 필드로 작성 = N:1 관계 명시
@JoinColumn(name="1 테이블의 PK 컬럼명")
1클래스
@OneToMany (mappedby="N클래스에서 가지고있는 1클래스의 필드명")
N:1 관계에서 1클래스에서 작성하며, N클래스를 List/Set 형태로 필드 선언 후 애너테이션 추가.
2. N:1 매핑이 종료된 이후, 1쪽에서 N쪽의 정보를 참조할 기능이 필요하다면 1:N 추가하여 양방향 처리.
1클래스
@OneToMany (mapped ="N클래스에서 필드로 선언한 1클래스의 객체명")
N클래스를 List/Set<N클래스명> 형태로 필드 선언
N:N -> N:1, 1:N 변경 시 -> [결론]
1 클래스 :
@OneToMany(mappedby= "N클래스에 있는 1 클래스의 필드명")
List<N클래스> 변수명 = new ArrayList<>();
N 클래스 :
@ManyToOne
@JoinColumn(name = "1 테이블의 PK 컬럼명)
1객체 변수명;
[DB속 조인 테이블에 값을 채우는 방법]
1. 엔티티 클래스에 필요한 필드들을 위와 같이 설정
2. 1의 객체를 생성할 때, 해당 1 객체에 필요한 필드 설정 후 DB에 저장.
3. 조인테이블 객체를 생성
4. 생성 후 조인테이블 객체에 1관계의 객체들을 set로 지정
5. 1객체에 조인테이블 객체 추가해주기.
6. 조인테이블 객체를 조인테이블 도메인의 repository를 생성하여 저장하기
@Transactional
@PostMapping("/{library-Id}")
public ResponseEntity postMember(@PathVariable("library-Id")@Positive Long libraryId,
@RequestBody @Valid MemberDto.Post post) throws Exception {
Member member = mapper.memberDtoPostToMember(post);
member.setLibraryId(libraryId);
Member createdMember = memberService.createMember(member);
LibraryMember libraryMember = new LibraryMember();
libraryMember.setMember(member);
libraryMember.setLibrary(libraryService.findLibrary(libraryId));
member.getLibraryMembers().add(libraryMember);
libraryMemberRepository.save(libraryMember);
MemberDto.Response response = mapper.memberToMemberDtoResponse(createdMember);
response.setUrl(url + response.getMemberId());
HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Expose-Headers","Authorization");
return new ResponseEntity(response, headers, HttpStatus.CREATED);
}
[1:N 관계에서 1객체를 지울 때 주의사항]
1. 1 : N 관계에 있는 객체들 중 1 객체를 삭제할 때는 1객체를 외래키 로써 가지고 있는 N 객체를 지워야함.
1객체 삭제 전 JPQL을 사용하여 1객체의 id를 사용해 N객체를 먼저 지워야 한다.
Ex) Member : MemberBook
memberBookRepository.deleteByMember_Id(memberId);
memberService.deleteMember(memberId);
<MemberBookRepository>
@Transactional
@Modifying
@Query("DELETE FROM MemberBook mb WHERE mb.member.id =:memberId")
void deleteByMember_Id(@Param("memberId") Long memberId);
2. @OneToMany 애너테이션에서 cascade = CascadeType.REMOVE or ALL 을 사용
하지만 N 관계에 있는 객체가 1객체의 애그리거트 루트 (핵심 관계)가 아닐 경우라면 지양해야 한다.
즉, 1관계, N관계 객체가 서로 밀접한 관계가 아니라면,
MemberBook 객체가 Member 객체 없이 존재 할 수 있다면 Cascade 사용하면 안된다.
B-4 : [1:1 관계]
양쪽의 엔티티 클래스 필드에 상대 클래스 객체 선언.
@OneToOne(mappedby="상대클래스 필드에 선언된 본인 클래스명", cascade = CascadeType.PERSIST)
@JoinColumn(name="상대1클래스_테이블의_PK컬럼명)
상대_1클래스_필드
'Tips' 카테고리의 다른 글
JUnit Test 코드 TIP (0) | 2023.05.16 |
---|---|
Spring Data JPA VS JPQL and QueryDsl (0) | 2023.05.15 |
Mapstruct @Mapping(target = , source = ) (0) | 2023.05.13 |
Spring Data JPA - 자동 완성 메서드 규칙 (0) | 2023.05.12 |
JPQL 예시 (0) | 2023.05.12 |