mentor

박경희·2023년 8월 25일
1

프로젝트

목록 보기
7/16
post-thumbnail

Entity

@Entity
@Getter @Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "mentors")
public class Mentor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToOne
    private User user;
    
    private String majorCareer;
    
    @OneToMany(mappedBy = "mentor", fetch = FetchType.LAZY, orphanRemoval = true)
    private List<MentorMentoringField> mentoringFields;
    
    private String introduction;
    private String company;
    private String department;
    private String profilePicture;
}

➡️ OneToOne은 잘 사용하지 않는다고 했지만, 우리는 로그인한 유저 아이디하나당 1개의 mentor지원이 가능하기 때문에 OneToOne을 사용했다.

➡️ 처음 계획할 때는 MentoringField를 그냥 string으로 만들어줬는데 코드를 짜고 실제 운영될 서비스를 생각해 보니 멘토와 멘토링필드는 다대다 관계가 되어야할 것 같아서 중간 테이블을 만들고 연결해주었다.

➡️ jpa 연관관계 삭제 : orphanRemoval = true를 붙여주면 된다.
멘토에게 멘토링필드를 넣다가 기존에 넣었던 필드를 지우고 다른 필드를 넣고 싶어졌다.
그런데 여기서 문제가 생겼다.
멘토가 가지고 있는 필드를 지우면 필드 자체가 데이터베이스에서 삭제되기 떄문에 다른 멘토들에서도 이 필드들이 삭제되어버리는 것이다. 그래서 해당 유저의 원하는 필드만을 지우기 위해 'jpa 연관관계 삭제'를 검색해보니 orphanRemoval = true를 붙여주면 된다고 했다. 그래서 orphanRemoval = true를 붙이고 삭제를 해보니 내가 원하는대로 잘 삭제되었다.
다른 멘토링필드로 바꾸기 위해 삭제를 할 필요가 생겼다.

Controller

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/mentors")
public class MentorController {

    private final MentorService mentorService;
    private final KakaoService kakaoService;
    
    @PostMapping
    public void insert(@RequestBody MentorRequest request,@CookieValue(value = "Token", required = false) Cookie cookie) {
        User user = kakaoService.getUserInfo(cookie.getValue());
        mentorService.save(request,user);
    }

    @GetMapping("{id}")
    public MentorResponse getById(@PathVariable("id") Long id) {
        return mentorService.findById(id);

    }

    @GetMapping
    public List<MentorResponse> getAll() {
        List<MentorResponse> all = mentorService.findAll();
        return all;
    }

    @DeleteMapping("{id}")
    public void deleteById(@PathVariable("id") Long id) {
        mentorService.deleteMentorId(id);

    }

    @PutMapping("{id}")
    public void changeDate(@PathVariable("id") Long id,
                           @RequestBody MentorRequest request) {
        mentorService.changeDate(id, request);
    }

	//멘토에 필드 저장
    @PostMapping("/field")
    public void save(@RequestBody ConnectRequest request) {
        mentorService.connect(request);

    }
	
    // 멘토링 필드를 리스트로 받는 과정에 코드를 수정하여 그에 맞게 수정이 조금 필요함.
    @DeleteMapping("{userId}/{mentoringFieldId}")
    public void deleteMentoringField(@PathVariable("userId") Long userId,
                                     @PathVariable("mentoringFieldId") Long mentoringFieldId) {
        mentorService.mentorFieldDelete(userId, mentoringFieldId);

    }
}

Service

@Service
@RequiredArgsConstructor
@Transactional
public class MentorService {
    private final MentorRepository mentorRepository;
    private final UserRepository userRepository;
    private final MentoringFieldRepository fieldRepository;
    private final MentorMentoringFieldRepository mentoringFieldRepository;

    //멘토 등록
    public void save(MentorRequest request,User user) {
        Mentor mentor = Mentor.builder()
                .user(user)
                .majorCareer(request.getMajorCareer())
                .mentoringFields(null)
                .introduction(request.getIntroduction())
                .company(request.getCompany())
                .department(request.getDepartment())
                .picture(request.getPicture())
                .build();
        mentorRepository.save(mentor);
    }

    //id로 찾기
    public MentorResponse findById(Long id) {
        Optional<Mentor> byId = mentorRepository.findById(id);

        MentorResponse mentorResponse = MentorResponse.builder()
                .mentorId(byId.get().getId())
                .company(byId.get().getCompany())
                .department(byId.get().getDepartment())
                .majorCareer(byId.get().getMajorCareer())
                .picture(byId.get().getPicture())
                .username(byId.get().getUser().getUsername())
                .introduction(byId.get().getIntroduction())

                .mentoringFields(byId.get().getMentoringFields() != null ?
                        byId.get().getMentoringFields()
                                .stream()
                                .map(MentorMentoringField::getMentoringField)
                                .map(MentoringFieldDto::new)
                                .toList()
                                : new ArrayList<>())
                .build();
        return mentorResponse;
    }

    //멘토 전체 찾기
    public List<MentorResponse> findAll() {
        List<Mentor> all = mentorRepository.findAll();
        return all.stream().map(m-> new MentorResponse(m)).toList();
    }

    //멘토 삭제
    public void deleteMentorId(Long id) {
        mentorRepository.deleteById(id);
    }

    //멘토 정보 업데이트
    public MentorResponse changeDate(Long id, MentorRequest request) {
        Optional<Mentor> byId = mentorRepository.findById(id);
        if (byId.isEmpty()) throw new RuntimeException("멘토 정보가 없습니다.");

        User user = userRepository.findById(id).orElseThrow();

        Mentor mentor = new Mentor(id, user, request.getMajorCareer(), null,
                request.getIntroduction(), request.getCompany(), request.getDepartment(), request.getPicture());
        Mentor save = mentorRepository.save(mentor);
        return new MentorResponse(save);
    }

    //멘토와 멘토링필드 연결
    public void connect(ConnectRequest request) {
        Mentor mentor = Mentor.builder()
                .id(request.getMentorId())
                .build();
        MentoringField mentoringField = MentoringField.builder()
                .id(request.getMentoringFieldId())
                .build();

        //중복처리
        MentorMentoringField mentorMentoringField = mentoringFieldRepository.findByMentorAndMentoringField(mentor, mentoringField)
                .orElse(null);
        if (mentorMentoringField == null) {
            mentorMentoringField = MentorMentoringField.of(mentor, mentoringField);
            mentoringFieldRepository.save(mentorMentoringField);
        }
    }

    //유저가 가지고 있는 field 지우기
        public void mentorFieldDelete(Long userId, Long mentoringFieldId) {
        Mentor mentor = Mentor.builder()
                .id(userId)
                .build();
        MentoringField mentoringField = MentoringField.builder()
                .id(mentoringFieldId)
                .build();


        MentorMentoringField mentorMentoringField = mentoringFieldRepository.findByMentorAndMentoringField(mentor, mentoringField)
                .orElse(null);
        mentoringFieldRepository.delete(mentorMentoringField);

    }

}

Repository

@Repository
public interface MentorRepository extends JpaRepository<Mentor, Long> {

}

Request

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class MentorRequest {
    private Long userId;
    private String majorCareer;
    private String introduction;
    private String company;
    private String department;
    private Long mentoringFieldId;
    private String profilePicture;
}

Response

@AllArgsConstructor //모든 필드를 인자로 받는 생성자를 생성
@NoArgsConstructor // 파라미터 없는 디폴트 생성자를 생성
@Getter
@Builder
public class MentorResponse {
    private Long userId;
    private Long mentorId;
    private String majorCareer;
    private String introduction;
    private String company;
    private String department;
    private String profilePicture;
    private String username;
    private String phoneNumber;
    private String email;
    private List<MentoringFieldDto> mentoringFields = new ArrayList<>();

	//Mentor 엔티티의 정보를 MentorResponse 객체로 변환
    public MentorResponse(Mentor mentor) {
        this.userId = mentor.getUser().getId();
        this.mentorId = mentor.getId();
        this.majorCareer = mentor.getMajorCareer();
        this.introduction = mentor.getIntroduction();
        this.company = mentor.getCompany();
        this.department = mentor.getDepartment();
        this.profilePicture = mentor.getProfilePicture();
        this.username = mentor.getUser().getUsername();
        this.phoneNumber = mentor.getUser().getPhoneNumber();
        this.email = mentor.getUser().getEmail();
        
        //연관관계 끊어주기.
        //mentoringFields라는 필드를 초기화하는 부분
        //Mentor 엔티티에서 가져온 MentoringField 정보를 MentorResponse 객체의 mentoringFields 필드로 설정하는 역할
        this.mentoringFields = mentor.getMentoringFields() != null ? //Mentor 엔티티에 연결된 MentoringField들이 존재한다면 이 블록이 실행
                mentor.getMentoringFields()
                        .stream()
                        .map(MentorMentoringField::getMentoringField)
                        .map(MentoringFieldDto::new)
                        .toList() //앞선 연산들을 통해 생성된 MentoringFieldDto 스트림을 리스트로 변환
                :new  ArrayList<>(); 

    }
}

✅ 연관관계 끊는 방법 이해하기.

'mentor.getMentoringFields().stream()'
➡️ mentoringFields 필드에 연결된 MentoringField 엔티티들을 스트림으로 변환.
이 스트림을 통해 각 MentoringField에 대한 작업을 수행할 수 있게된다.

'.map(MentorMentoringField::getMentoringField)'
➡️ MentoringField 엔티티에 있는 getMentoringField 메서드를 호출하여, 각 MentoringField 엔티티를 MentoringField 객체로 변환.
➡️ 이 메서드 호출에 의해 MentoringField 엔티티의 정보를 가져오는 것

'.map(MentoringFieldDto::new)'
➡️ 앞서 얻은 MentoringField 객체들을 MentoringFieldDto로 변환하는 것이다. 이 때, MentoringFieldDto의 생성자가 호출된다.

'.map(MentoringFieldDto::new)'
➡️ 앞선 연산들을 통해 생성된 MentoringFieldDto 스트림을 리스트로 변환

Dto

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class MentorDto {
    private Long mentorId;
    private String majorCareer;
    private String introduction;
    private String company;
    private String department;
    private String profilePicture;

    public MentorDto(Mentor mentor) {
        this.mentorId = mentor.getId();
        this.majorCareer = mentor.getMajorCareer();
        this.introduction = mentor.getIntroduction();
        this.company = mentor.getCompany();
        this.department = mentor.getDepartment();
        this.profilePicture = mentor.getProfilePicture();
    }

}

1개의 댓글

comment-user-thumbnail
2023년 8월 27일

크으으 잘 만들었네요 스트림도 쓰고 굿!

답글 달기

관련 채용 정보