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;
}