[프로젝트] 인스타그램(7) - 팔로우 팔로잉
다른 페이지
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로 바로 결과 나올 수 있게 구현하기만 하면 되니까 어렵지는 않을 것이다.