[ElectionPJT] 5. Sns_Entity, Repository, Service

Jake·2022년 3월 16일
0

프로젝트

목록 보기
5/9

1. 지원 기능

  • 게시물 추가
  • 게시물 삭제
  • 게시물 수정

매체 별로 repository, service를 분리하여 구현


2. 매체 별 엔티티를 분리한 이유

  • Vote22 앱을 운영하면서 매체 별로 운영 방식이 달라야 한다고 느꼈기 때문인데, 그 이유는
    • 모든 sns 앱들이 좋아요, 댓글 수 등의 기능을 지원한다고는 하나 이 기능들을 운영하는 방식이 모두 다르다.
      일례로 인스타그램의 경우 다른 sns들과 달리, 정확한 좋아요 수를 알려주지 않음.
      이렇듯 매체의 특성이 모두 다르기 때문에, 매체 별로 비즈니스 로직도 달라야 한다고 생각해서 sns 엔티티와 상속관계를 맺어 분리했다.

3. Repository

Sns Repository (조회 기능만 존재)

@Repository
@RequiredArgsConstructor
public class SnsRepository {

    private final EntityManager em;

    public List<Sns> findAll() {
        return em.createQuery("select s from Sns s", Sns.class)
                .getResultList();
    }
}

Facebook Repository(게시물 추가, 삭제, 수정)

@Repository
@RequiredArgsConstructor
public class FacebookRepository {

    private final EntityManager em;

    public void save(Facebook facebook) {
        em.persist(facebook);
    }

    public void remove(Facebook facebook) {
        em.remove(facebook);
    }

    public Facebook findById(Long id) {
        return em.find(Facebook.class, id);
    }

    public List<Facebook> findAllByCandidateId(Long candidateId) {
        return em.createQuery("select f from Facebook f" +
                        " where f.candidate.id = :candidateId", Facebook.class)
                .setParameter("candidateId", candidateId)
                .getResultList();
    }
}

Instagram, Twitter repository는 여기서는 생략하겠습니다.
전체 코드는 여기에서 확인해주세요.


4. Service

Sns Service

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class SnsService {

    private final SnsRepository snsRepository;

    /**
     * Sns 전체 조회
     */
    public List<Sns> findSnsList() {
        return snsRepository.findAll();
    }
}

Facebook Service

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class FacebookService {

    private final FacebookRepository facebookRepository;
    private final CandidateRepository candidateRepository;

    @Transactional
    public Long join(FacebookRequestDto facebookRequestDto) {
        Long candidateId = facebookRequestDto.getCandidateId();
        Candidate candidate = candidateRepository.findById(candidateId);

        Facebook facebook = facebookRequestDto.toEntity(candidate);
        facebookRepository.save(facebook);

        return facebook.getId();
    }

    @Transactional
    public void delete(Long facebookId) {
        Facebook facebook = facebookRepository.findById(facebookId);
        facebookRepository.remove(facebook);
    }

    @Transactional
    public void update(Long facebookId, FacebookUpdateDto facebookUpdateDto) {
        Facebook facebook = facebookRepository.findById(facebookId);
        facebook.change(
                facebookUpdateDto.getLikes(),
                facebookUpdateDto.getComments(),
                facebookUpdateDto.getShares()
        );
    }

    public FacebookResponseDto findFacebook(Long facebookId) {
        Facebook facebook = facebookRepository.findById(facebookId);
        return new FacebookResponseDto(facebook);
    }

    public List<FacebookResponseDto> findFacebookList(Long candidateId) {
        return facebookRepository.findAllByCandidateId(candidateId).stream()
                .map(FacebookResponseDto::new)
                .collect(Collectors.toList());
    }
}

Instagram 및 Twitter service와 dto 관련 부분은 생략하겠습니다.
전체 코드는 여기에서 확인해주세요.


5. 테스트 코드

테스트 요구사항

  • 게시물 추가
  • 게시물 삭제
  • 게시물 수정

테스트 코드

@SpringBootTest
@Transactional
public class SnsServiceTest {

    @Autowired CityRepository cityRepository;
    @Autowired CandidateRepository candidateRepository;
    @Autowired SnsService snsService;
    @Autowired FacebookRepository facebookRepository;
    @Autowired FacebookService facebookService;
    @Autowired InstagramService instagramService;
    @Autowired TwitterService twitterService;

    @Test
    public void sns_추가() throws Exception {
        //given
        Candidate candidate = createCandidate();

        //when
        facebookService.join(new FacebookRequestDto(candidate.getId(), "content1", "url", LocalDateTime.now(), 1, 1, 1));
        instagramService.join(new InstagramRequestDto(candidate.getId(), "content1", "url", LocalDateTime.now(), 1, 1));
        twitterService.join(new TwitterRequestDto(candidate.getId(), "content1", "url", LocalDateTime.now(), 1, 1, 1));

        //then
        List<Sns> snsList = snsService.findSnsList();
        List<TwitterResponseDto> twitterList = twitterService.findTwitterList(candidate.getId());

        assertEquals(3, snsList.size());
        assertEquals(1, twitterList.size());
    }

    @Test
    public void sns_삭제() throws Exception {
        //given
        Candidate candidate = createCandidate();
        Facebook facebook = new Facebook(candidate, "content1", "url", LocalDateTime.now(), 1, 1, 1);
        facebookRepository.save(facebook);

        //when
        facebookService.delete(facebook.getId());

        //then
        List<FacebookResponseDto> facebookList = facebookService.findFacebookList(candidate.getId());
        assertEquals(0, facebookList.size());

    }

    @Test
    public void sns_수정() throws Exception {
        //given
        Candidate candidate = createCandidate();
        Facebook facebook = new Facebook(candidate, "content1", "url", LocalDateTime.now(), 1, 1, 1);
        facebookRepository.save(facebook);

        FacebookUpdateDto facebookUpdateDto = FacebookUpdateDto.builder()
                                                    .likes(2)
                                                    .comments(1)
                                                    .shares(1)
                                                    .build();


        //when
        facebookService.update(facebook.getId(), facebookUpdateDto);

        //then
        assertEquals(2, facebookService.findFacebook(facebook.getId()).getLikes());
    }
    
    private City createCity() {
        District district = new District("서울", "서울특별시 종로구", "서울 종로");
        City city = new City(district);
        cityRepository.save(city);
        return city;
    }

    private Candidate createCandidate() {
        City city = createCity();
        Candidate candidate = new Candidate(1, "Jake", city);
        candidateRepository.save(candidate);
        return candidate;
    }
}

테스트 결과

profile
Java/Spring Back-End Developer

0개의 댓글