2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글 05

 

spring vue 댓글 05

2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글04 spring vue 댓글04 2023.11.05 - [웹/Spring vue 웹 개발] - spring vue 댓글03 spring vue 댓글03 2023.10.14 - [웹/Spring vue 웹 개발] - spring vue 댓글 02 spring vue 댓글 02이전

kwaksh2319.tistory.com

일단 게시판도 조금 수정해야하는 부분도 있어서 완료했고요. 댓글들도 전부 달리도록 하였습니다.

이제 세션추가랑 유저구분할수 있도록 할거고요. 음 먼저 관리자 페이지는 제가 지금 다시 개발중이라 일단 개발되는데로 운영서버에 올릴 예정입니다. 아직 운영서버에는 적용이 안되었습니다.

영상:

이미지:

 

코드:

게시판 컨트롤러

@Slf4j
@RestController
@RequestMapping("/notice")
public class NoticeController {
   private final NoticeService noticeService;

    @Autowired
    public NoticeController(NoticeService noticeService){
        this.noticeService=noticeService;
   }

   @PostMapping
   public ResponseEntity<Notice> save(@RequestBody Notice notice){
        return ResponseEntity.ok(noticeService.save(notice));
   }

    @GetMapping
    public ResponseEntity< Map<String,List> > findAll(){
        return ResponseEntity.ok( noticeService.findAllWithComments(1));
    }

   @GetMapping("/{page}")
    public ResponseEntity< Map<String,List> > findAll(@PathVariable int page){
        return ResponseEntity.ok( noticeService.findAllWithComments(page));
   }

   @GetMapping("/{page}/{id}")
   public ResponseEntity<Notice> findWithCommentsById(@PathVariable int page,@PathVariable Long id){
        Optional<Notice> notice=noticeService.findWithCommentsById(page,id);
        return ResponseEntity.ok( notice.get() );
   }

   @PutMapping("/{id}")
   public ResponseEntity<Notice> update(@PathVariable Long id, @RequestBody Notice notice){
       return ResponseEntity.ok(noticeService.update(id,notice));
   }

   @DeleteMapping
   public void deleteAll(){
        noticeService.deleteAll();
   }
}

게시판 서비스 

package kr.co.kshproject.webDemo.Applicaiton.Notice;

import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeCustomRepository;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeRepository;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Slf4j
@Service
public class NoticeServiceImpl implements NoticeService {
    private static final Logger logger = LoggerFactory.getLogger(NoticeServiceImpl.class);

    private final NoticeRepository noticeRepository;

    private final NoticeCustomRepository noticeCustomRepository;

    @Autowired
    public NoticeServiceImpl(NoticeRepository noticeRepository,NoticeCustomRepository noticeCustomRepository){
        this.noticeRepository=noticeRepository;
        this.noticeCustomRepository=noticeCustomRepository;
    }

    @Override
    public Notice save(Notice notice) {
        LocalDate now = LocalDate.now();
        notice.setCreatedDate(now.toString());
        notice.setUsername("admin");
        return noticeRepository.save(notice);
    }
    
    @Override
    public List<Notice> findAll() {
        return noticeRepository.findAll();
    }

    @Override
    public Optional<Notice> findById(Long id) {
        return noticeRepository.findById(id);
    }

    @Override
    public Map<String,List> findAllWithComments(int page) {
        //admin get pagesize;
        int pageSize=10;
        return noticeCustomRepository.findAllWithComments(page,pageSize);
    }

    @Override
    public Optional<Notice> findWithCommentsById(int page,Long id) {
        Optional<Notice> result= noticeCustomRepository.findWithCommentsById(page,id);
        return result;
    }

    @Override
    public Notice update(Long id,Notice saveNotice) {
        Optional<Notice> findNotice = noticeRepository.findById(id);

        if(findNotice.isPresent()==false){
            return null;
        }

        Notice notice=findNotice.get();
        notice.setTitle(saveNotice.getTitle());
        notice.setContents(saveNotice.getContents());
        return noticeRepository.save(notice);
    }
    @Override
    public void deleteAll() {
        noticeRepository.deleteAll();
    }
}

게시판 레파지토리

import org.springframework.stereotype.Repository;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Repository
public interface NoticeCustomRepository {
    public Map<String, List> findAllWithComments(int page, int pageSize);

     Long findAllCountNotice(CriteriaBuilder cb);
    Optional<Notice> findWithCommentsById(int page,Long id) ;
}

게시판 레파지토리

import lombok.extern.slf4j.Slf4j;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class NoticeRepositoryImpl implements NoticeCustomRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Map<String,List> findAllWithComments(int page, int pageSize) {
        List<Long> totalSize =new LinkedList<>();
        Map<String,List> noticeDTOList=new ConcurrentHashMap<>();

        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //NoticeDTO <= Notice 커멘트 사용하지 않기 위함
        CriteriaQuery<NoticeDTO> cq = cb.createQuery(NoticeDTO.class);

        //from 절
        Root<Notice> notice = cq.from(Notice.class);
        //SELECT id,username,title,contents,email,createdDate FROM Notice LIMIT [pageSize] OFFSET (page-1) * [pageSize] ;
        cq.select(cb.construct(
                NoticeDTO.class,
                notice.get("id"),
                notice.get("username"),
                notice.get("title"),
                notice.get("contents"),
                notice.get("email"),
                notice.get("createdDate")
        ));
        //cq 쿼리 실행
        TypedQuery<NoticeDTO> query = entityManager.createQuery(cq);
        //게시판 총사이즈
        Long tSize=findAllCountNotice(cb);
        tSize=tSize/pageSize+1;
        totalSize.add(tSize);

        //cq 쿼리 실행 후 페이지 갯수만큼 불러오기
        query.setFirstResult( (page-1) *pageSize);
        query.setMaxResults(pageSize);

        //맵리스트 저장
        noticeDTOList.put("lists",query.getResultList());
        noticeDTOList.put("totalSize",totalSize);

        //결과값 리턴
        return noticeDTOList;
    }

    @Override
    public Long findAllCountNotice(CriteriaBuilder cb) {
        //게시판 총 카운트
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<Notice> countRoot = countQuery.from(Notice.class);
        countQuery.select(cb.count(countRoot));
        Long totalRecords = entityManager.createQuery(countQuery).getSingleResult();
        return totalRecords;
    }


    @Override
    public Optional<Notice> findWithCommentsById(int page,Long id)  {

        //Criteria API 사용
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        //Notice 사용 이유는 댓글들을 불러오기때문
        CriteriaQuery<Notice> cq = cb.createQuery(Notice.class);

        /*select * from Notice LEFT JOIN Comments where id='id'*/
        //from Notice
        Root<Notice> notice = cq.from(Notice.class);
        //left join
        notice.fetch("comments", JoinType.LEFT);
        cq.where(cb.equal(notice.get("id"), id));
        //cq 쿼리 실행
        TypedQuery<Notice> query = entityManager.createQuery(cq);
        List<Notice> result = query.getResultList();
        //삼항 연산자 result 비엇을시 empty() 존재지 resutl 리턴
        return result.isEmpty() ? Optional.empty(): Optional.of(result.get(0));
    }
}

게시판 dto

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class NoticeDTO {
    private Long id;
    private String username;
    private String title;
    private String contents;
    private String email;
    private String createdDate;

    // Constructor that takes an entity Notice
    public NoticeDTO(Notice notice) {
        this.id = notice.getId();
        this.username = notice.getUsername();
        this.title = notice.getTitle();
        this.contents = notice.getContents();
        this.email = notice.getEmail();
        this.createdDate = notice.getCreatedDate();
    }
}

게시판 테이블

import com.fasterxml.jackson.annotation.JsonManagedReference;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "Notice")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Notice {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "NOTICE_SEQ")
    @SequenceGenerator(name = "NOTICE_SEQ", sequenceName = "NOTICE_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Long id; //key

    @NotEmpty
    @Setter
    private String username;

    @NotEmpty
    @Setter
    private String title;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    private String email;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;

    @JsonManagedReference
    @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Comment> comments = new ArrayList<>();
}

댓글 컨트롤러

import kr.co.kshproject.webDemo.Applicaiton.Comment.CommentService;
import kr.co.kshproject.webDemo.Domain.Comment.Comment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/comment")
public class CommentController {
    private final CommentService commentService;

    @Autowired
    public CommentController(CommentService commentService){
        this.commentService=commentService;
    }

    @PostMapping("/{page}/{id}")
    public ResponseEntity<Comment> save(@PathVariable int page, @PathVariable Long id, @RequestBody Comment comment) {
        return ResponseEntity.ok(commentService.save(page,id,comment));
    }

    @GetMapping
    public ResponseEntity<List<Comment>> findAll(){
        return ResponseEntity.ok( commentService.findAll());
    }

    @GetMapping("/{id}")
    public Optional<Comment> findById(@PathVariable Long id){
        return commentService.findById(id);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Comment> update(@PathVariable Long id, @RequestBody Comment comment){
        return ResponseEntity.ok(commentService.update(id,comment));
    }

    @DeleteMapping
    public void deleteAll(){
        commentService.deleteAll();
    }
}

 

댓글 서비스

package kr.co.kshproject.webDemo.Applicaiton.Comment;

import kr.co.kshproject.webDemo.Domain.Comment.Comment;

import java.util.List;
import java.util.Optional;

public interface CommentService {
    Comment save(int page,Long noticeId,Comment comment);
    List<Comment> findAll();
    Optional<Comment> findById(Long id);
    Comment update(Long id,Comment saveComment);
    void deleteAll();
}
package kr.co.kshproject.webDemo.Applicaiton.Notice;

import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeCustomRepository;
import kr.co.kshproject.webDemo.Domain.Notice.NoticeRepository;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Slf4j
@Service
public class NoticeServiceImpl implements NoticeService {
    private static final Logger logger = LoggerFactory.getLogger(NoticeServiceImpl.class);

    private final NoticeRepository noticeRepository;

    private final NoticeCustomRepository noticeCustomRepository;

    @Autowired
    public NoticeServiceImpl(NoticeRepository noticeRepository,NoticeCustomRepository noticeCustomRepository){
        this.noticeRepository=noticeRepository;
        this.noticeCustomRepository=noticeCustomRepository;
    }

    @Override
    public Notice save(Notice notice) {
        LocalDate now = LocalDate.now();
        notice.setCreatedDate(now.toString());
        notice.setUsername("admin");
        return noticeRepository.save(notice);
    }

    @Override
    public List<Notice> findAll() {
        return noticeRepository.findAll();
    }

    @Override
    public Optional<Notice> findById(Long id) {
        return noticeRepository.findById(id);
    }

    @Override
    public Map<String,List> findAllWithComments(int page) {
        //admin get pagesize;
        int pageSize=10;
        return noticeCustomRepository.findAllWithComments(page,pageSize);
    }

    @Override
    public Optional<Notice> findWithCommentsById(int page,Long id) {
        Optional<Notice> result= noticeCustomRepository.findWithCommentsById(page,id);
        return result;
    }

    @Override
    public Notice update(Long id,Notice saveNotice) {
        Optional<Notice> findNotice = noticeRepository.findById(id);

        if(findNotice.isPresent()==false){
            return null;
        }

        Notice notice=findNotice.get();
        notice.setTitle(saveNotice.getTitle());
        notice.setContents(saveNotice.getContents());
        return noticeRepository.save(notice);
    }
    @Override
    public void deleteAll() {
        noticeRepository.deleteAll();
    }
}

댓글 레파지토리

package kr.co.kshproject.webDemo.Domain.Comment;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CommentRepository extends JpaRepository<Comment,Long> {
}

댓글 테이블

import com.fasterxml.jackson.annotation.JsonBackReference;
import kr.co.kshproject.webDemo.Domain.Notice.Notice;
import lombok.*;
import javax.persistence.*;
import javax.validation.constraints.NotEmpty;

@Entity
@Table(name = "Comment")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COMMENT_SEQ")
    @SequenceGenerator(name = "COMMENT_SEQ", sequenceName = "COMMENT_SEQ", allocationSize = 1)
    private Long id;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="notice_id")
    @Setter
    private Notice notice;

    @NotEmpty
    @Setter
    private String userName;

    @NotEmpty
    @Setter
    private String contents;

    @NotEmpty
    @Setter
    @Column(name = "created_date")
    private String createdDate;
}

' > Spring vue 웹 개발' 카테고리의 다른 글

spring vue entity 변경  (2) 2023.11.25
spring vue 어드민 리팩토링01  (0) 2023.11.18
spring vue 댓글 05  (1) 2023.11.11
spring vue 댓글04  (1) 2023.11.11
spring vue 댓글03  (0) 2023.11.05

+ Recent posts