[프로젝트] 인스타그램(7) - 팔로우 팔로잉

2 분 소요

다른 페이지

https://sjj02055.github.io/projects/instagram_1/ https://sjj02055.github.io/projects/instagram_2/ https://sjj02055.github.io/projects/instagram_3/ https://sjj02055.github.io/projects/instagram_4/ https://sjj02055.github.io/projects/instagram_5/ https://sjj02055.github.io/projects/instagram_6/

실행 환경

Intellij, Oracle

사용 Tools

SpringBoot, Thymeleaf, Lombok, json-simple, JPA

팔로우 팔로잉

Follow.java

package com.example.demo.domain;

import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.sql.Timestamp;

@Entity
@DynamicUpdate
@Getter @Setter
public class Follow {

    @Id
    @GeneratedValue
    Long id;

    @ManyToOne
    @JoinColumn(name = "following")
    Member following;

    @ManyToOne
    @JoinColumn(name = "follower")
    Member follower;

    Timestamp followDate;
}

제일 기본적인 follow domain.

FollowController.java

package com.example.demo.controller;

import com.example.demo.domain.Follow;
import com.example.demo.domain.Member;
import com.example.demo.service.FollowService;
import com.example.demo.service.MemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.sql.Timestamp;

@Controller
@Slf4j
@RequiredArgsConstructor
public class FollowController {

    private final FollowService followService;
    private final MemberService memberService;

    @PostMapping("/follow")
    public String follow(HttpServletRequest request, Model model){
        HttpSession session = request.getSession(false);
        Member loginMember = (Member)session.getAttribute("loginMember");

        Long user_id = loginMember.getId();
        Long following_id = Long.parseLong(request.getParameter("following_id"));
        log.info("following_id={}",following_id);

        Follow f = new Follow();
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        f.setFollowDate(timestamp);
        f.setFollower(loginMember);
        f.setFollowing(memberService.find(following_id));

        followService.follow(f);

        return "redirect:/petmily/profile/" + following_id;
    }

    @PostMapping("/unfollow")
    public String unfollow(HttpServletRequest request, Model model){
        HttpSession session = request.getSession(false);
        Member loginMember = (Member)session.getAttribute("loginMember");


        Long user_id = loginMember.getId();
        Long following_id = Long.parseLong(request.getParameter("following_id"));

        followService.unfollow(followService.find(following_id, user_id));

        return "redirect:/petmily/profile/" +following_id;
    }
}

follow와 unfollow는 다음과 같이 만들어두고 프론트에서 th:if 써서 follow 되어 있을때는 unfollow뜨게 그 반대는 follow뜨게 해두면 끝이고

FollowRepository.java

package com.example.demo.repository;

import com.example.demo.domain.Follow;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

@Repository
@Slf4j
@RequiredArgsConstructor
public class FollowRepository {

    private final EntityManager em;

    public void save(Follow f){
        em.persist(f);
    }

    public void delete(Follow f){
        em.remove(f);
    }

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

    public Optional<Follow> checkByFollowingIdAndFollwerId(Long page_id, Long user_id){
        return findAll().stream()
                .filter(f -> f.getFollower().getId().equals(user_id))
                .filter(f -> f.getFollowing().getId().equals(page_id))
                .findFirst();
    }

    public List<Follow> findByFollowerId(Long id){
        return em.createQuery("select f from Follow f where f.follower.id =:id", Follow.class)
                .setParameter("id" ,id)
                .getResultList();
    }

}

repository를 만들 때, 람다식을 짜는 것이랑 쿼리문 짜는게 가장 어려웠다. 이거 만드는데 구글링 열심히 해가면서 원하는 결과 얻으려고 정말 많이 노력한 것 같다.

FollowService.java

package com.example.demo.service;

import com.example.demo.domain.Follow;
import com.example.demo.repository.FollowInterfaceRepository;
import com.example.demo.repository.FollowRepository;
import com.example.demo.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.List;

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

    private final FollowRepository followRepository;
    private final FollowInterfaceRepository followInterfaceRepository;

    @Transactional
    public void follow(Follow f){
        followRepository.save(f);
    }

    @Transactional
    public void unfollow(Follow f){
        followRepository.delete(f);
    }

    public Follow find(Long page_id, Long user_id){
        return followRepository.checkByFollowingIdAndFollwerId(page_id, user_id).orElse(null);
    }

    public List<Follow> findByFollowerId(Long id){
        return followRepository.findByFollowerId(id);
    }
    public List<Follow> findByFollowingId(Long id){
        return followInterfaceRepository.findByFollowingId(id);
    }
    public List<Follow> findByFollower(Long id){
        return followInterfaceRepository.findByFollowerId(id);
    }

    public int countByFollowerId(Long id){
        return followInterfaceRepository.countByFollowerId(id);
    }

    public int countByFollowingId(Long id){
        return followInterfaceRepository.countByFollowingId(id);
    }
}

profile.html

<div th:unless="${member.id == loginMember.id}">
          <div th:if="${follow == null}">
            <form action="/follow" th:field="form" method="post">
              <input type="hidden" th:value="${member.id}" name="following_id">
              <button class="btn btn-submit" type="submit">팔로우</button>
            </form>
          </div>
          <div th:unless="${follow == null}">
            <form action="/unfollow" th:field="form" method="post">
              <input type="hidden" th:value="${member.id}" name="following_id">
              <button class="btn btn-submit" type="submit">언팔로우</button>
            </form>
          </div>
        </div>

후기

팔로우 언팔로우 기능을 완성했으니 검색 탭에서 유저를 검색할 수 있는 기능을 만들어 보자. 대충 DB에서 검색해서 ajax로 바로 결과 나올 수 있게 구현하기만 하면 되니까 어렵지는 않을 것이다.

카테고리:

업데이트: