어디까지 갈 수 있을까?

5 팔로우 본문

프로젝트/만남형 SNS

5 팔로우

_Min 2021. 6. 19. 20:14

팔로우 service

import com.post_show_blues.vine.domain.follow.FollowRepository;
import com.post_show_blues.vine.domain.member.MemberRepository;
import com.post_show_blues.vine.domain.notice.NoticeRepository;
import com.post_show_blues.vine.dto.NoticeResultDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;



@RequiredArgsConstructor
@Service
public class FollowService {
    private final FollowRepository followRepository;
    private final NoticeRepository noticeRepository;
    private final MemberRepository memberRepository;

    /**
     * 팔로우
     */
    @Transactional
    public void isFollow(long fromMemberId, long toMemberId){
        followRepository.rFollow(fromMemberId, toMemberId);
        noticeSave(fromMemberId, toMemberId);
    }

    /**
     * 언팔로우
     */
    @Transactional
    public void isUnFollow(long fromMemberId, long toMemberId){
        followRepository.rUnFollow(fromMemberId, toMemberId);
    }

    private void noticeSave(long fromMemberId, long toMemberId){
        String fromMemberNickname = memberRepository.findById(fromMemberId).get().getNickname();

        NoticeResultDTO noticeResultDTO = NoticeResultDTO.builder()
                .memberId(toMemberId)
                .text(fromMemberNickname + "님이 회원님을 팔로잉 했습니다.")
                .link("/member/"+fromMemberId)
                .build();

        noticeRepository.save(noticeResultDTO.toEntity());
    }
}

 사실 follow service의 메소드도 이름을 follow로 하고 싶었는데 그러면 엔티티 이름이랑 repository의 메소드 이름이랑 겹칠 것 같아서 차선책으로 isFollow로 지었다. 이런 경우 어떻게 해야될 지는 계속 고민해야 될 듯 하다

 

 우리 서비스는 인스타그램처럼 팔로우하면 알람테이블에 저장해놓는 구조이므로 follow 함과 동시에 테이블에 저장하도록 했다. link 에는 해당 메시지를 넣었을때 어디로 갈 지 주소값을 넣어봤다.

 

 

알림 dto

import com.post_show_blues.vine.domain.notice.Notice;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class NoticeResultDTO {

    private Long memberId;

    private String text;

    private String link;

    public Notice toEntity() {
        return Notice.builder()
                .memberId(memberId)
                .text(text)
                .link(link)
                .build();
    }

}

entity랑 모양 똑같은데 entity는 언제든지 변경될 수 있으니 dto를 따로 만들어주는게 좋을 듯 하다

 

 

팔로우 repository

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface FollowRepository extends JpaRepository<Follow, Long> {

    @Modifying
    @Query(value="INSERT INTO follow (from_member_id, to_member_id) VALUES (:fromMemberId, :toMemberId)", nativeQuery = true)
    void rFollow(@Param("fromMemberId") long fromMemberId,@Param("toMemberId") long toMemberId);

    @Modifying
    @Query(value="DELETE FROM follow WHERE from_member_id=:fromMemberId AND to_member_id=:toMemberId", nativeQuery = true)
    void rUnFollow(@Param("fromMemberId") long fromMemberId,@Param("toMemberId") long toMemberId);
}

insert를 할 때 Spring data JPA의 save()를 사용하면 되기 때문에 JPQL에는 insert 문이 없다. 그러므로 nativeQuery를 쓰자.

 

어차피 각각 받으므로 묶어줬다가 다시 나누지 말고 각각 나눠서 매핑해주자

 

 

팔로우 엔티티

import com.post_show_blues.vine.domain.member.Member;
import lombok.*;

import javax.persistence.*;

@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
@Table(
        uniqueConstraints = {
                @UniqueConstraint(
                        name="follow_uk",
                        columnNames={"from_member_id", "to_member_id"}
                )
        }
)
public class Follow {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="follow_id")
    private Long id;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="from_member_id",nullable = false)
    private Member fromMemberId; //팔로우 하는 멤버

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="to_member_id",nullable = false)
    private Member toMemberId; //팔로우 받는 멤버
}

XToOne은 fetch=FetchType.Lazy를 붙여주는 게 좋다고 한다. 안 그러면 연관관계에 있는 테이블 다 끌어와서 검색한다고 함.

 

 

팔로우 서비스 테스트

import com.post_show_blues.vine.domain.follow.Follow;
import com.post_show_blues.vine.domain.follow.FollowRepository;
import com.post_show_blues.vine.domain.member.Member;
import com.post_show_blues.vine.domain.member.MemberRepository;
import com.post_show_blues.vine.domain.notice.Notice;
import com.post_show_blues.vine.domain.notice.NoticeRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static org.assertj.core.api.Assertions.*;


@SpringBootTest
@Transactional
public class FollowServiceTest {

    @Autowired
    FollowService followService;
    @Autowired
    FollowRepository followRepository;
    @Autowired
    MemberRepository memberRepository;
    @Autowired
    NoticeRepository noticeRepository;

    Member memberA;
    Member memberB;


    @BeforeEach
    public void setup(){
        memberA = memberA();
        memberB = memberB();
        followService.isFollow(memberA.getId(), memberB.getId());
    }


    @Test
    public void 팔로우() throws Exception {
        //given
        //setup()에서 함
        System.out.println("memberA = " + memberA);

        //when
        List<Follow> followList = followRepository.findAll();
        Follow follow = followList.get(followList.size()-1);

        System.out.println("follow = " + follow);
        System.out.println(followList.contains(follow));

        //then
        assertThat(follow.getFromMemberId().getId()).isEqualTo(memberA.getId());
        assertThat(follow.getToMemberId().getId()).isEqualTo(memberB.getId());
    }

    @Test
    public void 알람테이블() throws Exception {
        //given
        //setup()에서 함

        //when
        List<Notice> noticeList = noticeRepository.findAll();
        Notice notice = noticeList.get(noticeList.size() - 1);

        //then
        assertThat(notice.getMemberId()).isEqualTo(memberB.getId());

    }


    @Test
    public void 언팔로우() throws Exception {
        //given
        System.out.println("memberA = " + memberA);
        List<Follow> followList = followRepository.findAll();
        Follow follow = followList.get(followList.size()-1);

        //when
        followService.isUnFollow(memberA.getId(), memberB.getId());
        List<Follow> unFollow = followRepository.findAll();

        //then
        assertThat(unFollow.contains(follow)).isEqualTo(false);
    }

    Member memberA() {
        Member memberA = Member.builder()
                .name("memberA")
                .email("member@duksung.ac.kr")
                .nickname("memberNickname")
                .password("1111")
                .phone("010-0000-0000")
                .university("덕성대학교")
                .build();
        memberRepository.save(memberA);
        return memberA;
    }

    Member memberB() {
        Member memberB = Member.builder()
                .name("memberB")
                .email("member@kookmin.ac.kr")
                .nickname("Nickname")
                .password("1111")
                .phone("010-0000-0000")
                .university("국민대학교")
                .build();

        memberRepository.save(memberB);
        return memberB;
    }


}

@BeforeEach

각각의 테스트 메소드 실행 전에 실행

 

List<Follow> followList = followRepository.findAll();
Follow follow = followList.get(followList.size()-1);
assertThat(follow.getFromMemberId().getId()).isEqualTo(memberA.getId());

사실 이 부분에서 이렇게 비교하는게 아니라 followRepository에 jpa쿼리메소드 형식으로 findByFromMemberIdAndToMemberId로 메소드를 만들려고 했었다.

그런데 테스트에서만 사용할 메소드를 실제 우리 서비스에 올라갈 코드에 넣는 건 아니라고 생각해서 테스트 클래스 안에서 extends FollowRepository로 클래스 하나 만들어서 메소드 집어넣었는데 안 돌아간다. 뭐지...? 배움의 부족인 것 같다 더 공부하는 걸로...

 

 

 

 

 

코드 깃헙 주소 https://github.com/JMine97/vine

참고 강의 https://www.easyupclass.com/course/218/about

  

 

728x90

'프로젝트 > 만남형 SNS' 카테고리의 다른 글

6 회원 프로필 사진 올리기  (0) 2021.06.22
4 회원정보수정  (0) 2021.06.05
3 로그인  (0) 2021.06.05
2 회원가입  (0) 2021.06.05
1 기획 및 DB스키마  (0) 2021.06.03
Comments