JPA 양방향 연관관계 편의 메소드
Intro
fuck I have been so confused with 양방향 mapping, even more so with the usage of Dtos but here it is
Explained
What I mean by 연관관계 편의 메소드 is that let’s say project and recruitment shares a @ManyToOne relationship like this
@Entity
@Getter
@NoArgsConstructor(access = PROTECTED)
public class Project extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "project_id")
private Long id;
@JoinColumn(name = "member_id")
private Long member_id;
//etc etc
@OneToMany(mappedBy = "project_recr", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Recruitment> recruitmentList = new ArrayList<>();
//연관관계 편의 메소드
public void addRecruitment(Recruitment recruitment){
if(this.recruitmentList!=null){
this.recruitmentList.removeIf(r -> r == null || r.getProject_recr() == null);
}
recruitmentList.add(recruitment);
recruitment.setProject_recr(this);
}
}
So for bi-directional JPA relationships, you have to put 연관관계 method, like this addRecruitment method.
Let’s look at this test case:
@Test
public void saveProjectWithDto(){
//given
List<RecruitmentDto> recruitmentDtoList = Arrays.asList(
RecruitmentDto.builder()
.recruitmentCount(3)
.recruitmentType("backend")
.recruitmentStatus("open")
.build(),
RecruitmentDto.builder()
.recruitmentCount(1)
.recruitmentType("frontend")
.recruitmentStatus("open")
.build());
ProjectDto projectDto = ProjectDto.builder()
.title("test")
.content("testing")
.email("random@gmail.com")
.url("hola.com")
.recruitmentDtoList(recruitmentDtoList)
.startDate(LocalDateTime.now())
.endDate(LocalDateTime.now())
.build();
//when
Project project = Project.toEntity(projectDto);
List<Recruitment> recruitmentList = Recruitment.toEntityList(recruitmentDtoList);
recruitmentList.forEach(recruitment -> project.addRecruitment(recruitment));
Project savedProject = projectRepository.save(project);
//then
assertThat(savedProject.getRecruitmentList().get(0).getRecruitmentCount()).isEqualTo(3);
}
So projectDto comes in with the project details and list of recruitment details like this
When we convert it to project entity, we can see that the recruitment in recruitmentList is not being mapped to the project field (project_recr is null).
So we use this addRecruitment method to first remove these recruitment in recruitmentList where project_recr field is null (through the if statement). Then, we properly set project field in recruitment and add the recruitment back to project entity’s recruitmentList. The result is:
Now we see project_recr field is mapped to each recruitment in project’s recruitmentList.
And when we save the project in our repository, the necessary fields like id, createdDate and modifiedDate (in BaseTimeEntity superclass) are automatically filled like this