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

아무거나