seong

(4)블로그만들기 - BoardsService 본문

Spring/블로그 만들기

(4)블로그만들기 - BoardsService

hyeonseong 2022. 9. 14. 10:31

만드는 순서 

1. 엔티티 만들기

2. Dao 만들기

3. Mapper(쿼리문) 작성 

4. Service 만들기 

    - 만들면서 필요한 Dto 생성 

5. ApiController로 테스트 

 

1. 엔티티 만들기 

package site.metacoding.red.domain.boards;

import java.sql.Timestamp;

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

@Getter
@Setter
public class Boards {
	private Integer id;
	private String title;
	private String content;
	private Integer usersId;
	private Timestamp createdAt; // At은 시분초 표현. Dt 년 월 일 
}

2. Dao 만들기

파라미터가 2개 이상은 @Param 어노테이션 사용해야 한다.

package site.metacoding.red.domain.boards;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import site.metacoding.red.web.dto.response.boards.MainDto;
import site.metacoding.red.web.dto.response.boards.PagingDto;

public interface BoardsDao {
	public void insert(Boards boards);
	public List<MainDto> findAll(@Param ("startNum")int startNum,@Param("keyword") String keyword);//파라미터 2개 
	public Boards findById(Integer id);
	public void update(Boards boards);
	public void deleteById(Integer id);
	public void updateByUsersId(Integer usersId);
	public PagingDto paging(@Param("page") Integer page, @Param("keyword")String keyword);//파라미터 2개 
	
}

3. BoardsMapper 작성(쿼리문)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="site.metacoding.red.domain.boards.BoardsDao">

	<select id="paging"
		resultType="site.metacoding.red.web.dto.response.boards.PagingDto">
		SELECT totalCount,
		totalPage,
		currentPage,
		if(currentPage = 0, 1, 0) first,
		if(currentPage = totalPage-1, 1, 0) last
		FROM
		(
		select count(*)
		totalCount, ceil(count(*)/3) totalPage,
		#{page} currentPage, 0
		first, 0
		last
		FROM boards
		<if test="keyword != null">
			WHERE title like CONCAT('%',#{keyword},'%')
		</if>
		) result
	</select>

	<insert id="insert">
		INSERT INTO boards(title, content, usersId,
		createdAt)
		VALUES(#{title}, #{content}, #{usersId},
		now())
	</insert>

	<select id="findById"
		resultType="site.metacoding.red.domain.boards.Boards">
		SELECT * FROM boards WHERE id=#{id}
	</select>

	<select id="findAll"
		resultType="site.metacoding.red.web.dto.response.boards.MainDto">
		SELECT *
		FROM boards b
		INNER JOIN
		users u
		ON
		b.usersId = u.id
		<if test="keyword != null">
			WHERE title like CONCAT('%',#{keyword},'%')
		</if>
		ORDER BY b.id DESC
		OFFSET #{startNum} ROWS
		FETCH NEXT 3 ROWS ONLY
	</select>

	<update id="update">
		UPDATE boards SET title = #{title}, content =
		#{content} WHERE id = #{id}
	</update>

	<delete id="deleteById">
		DELETE FROM boards WHERE id = #{id}
	</delete>

</mapper>

쿼리문 만들면서 시간이 걸렸던 곳

1. paging 쿼리문에서 마리아 DB는 Decode를 지원하지 않음 -> if문으로 바꾸어 작성

2. 쿼리문 인라인 뷰 사용에서는 Maria DB는 별칭이 필수!

3. Like문을 사용할 때 MariaDB는 CONCAT(문자1, 문자2, 문자3) 방식으로 연결

    -  WHERE title like CONCAT('%',#{keyword},'%')

4. Service 작성 

서비스는 @Service 어노테이션이 필요하다

package site.metacoding.red.service;

import java.util.List;

import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import site.metacoding.red.domain.boards.Boards;
import site.metacoding.red.domain.boards.BoardsDao;
import site.metacoding.red.domain.users.Users;
import site.metacoding.red.domain.users.UsersDao;
import site.metacoding.red.web.dto.request.boards.UpdateDto;
import site.metacoding.red.web.dto.request.boards.WriteDto;
import site.metacoding.red.web.dto.response.boards.MainDto;
import site.metacoding.red.web.dto.response.boards.PagingDto;

@RequiredArgsConstructor
@Service
public class BoardsService {
	
	private final BoardsDao boardsDao;
	private final UsersDao usersDao;
	
	public PagingDto 게시글목록보기(Integer page, String keyword) {
		if (page == null) {
			page = 0;
		}
		int startNum = page * 3; // 게시글 수 
		List<MainDto> boardsList = boardsDao.findAll(startNum, keyword);
		PagingDto pagingDto = boardsDao.paging(page, keyword);
		if (boardsList.size() == 0)
			pagingDto.setNotResult(true);
		pagingDto.makeBlockInfo(keyword);
		pagingDto.setMainDtos(boardsList);

		return pagingDto;
	}
	
	public Boards 게시글상세보기(Integer id) {
		Boards boards = boardsDao.findById(id);
		return boards;
	}
	
	public void 게시글수정하기(Integer id,UpdateDto updateDto) {//Integet id, Dto 
		//1. 영속화
		Boards boardsPS = boardsDao.findById(id);
		
		//2. 데이터업데이트
		boardsPS.update(updateDto);
		
		//3. 전체 업데이트
		boardsDao.update(boardsPS);
	}
	
	public void 게시글삭제하기(Integer id) {
		// 아이디 정보 가져와야함-> 영속
		Boards boardPS = boardsDao.findById(id);
		boardsDao.deleteById(id);
	}
	
	
	public void 게시글쓰기(WriteDto writeDto,Users principal) {
		boardsDao.insert(writeDto.toEntity(principal.getId()));
	}
	}

서비스 만들면서 추가한 Dto

1. UpdateDto (클라이언트의 요청)

2. WriteDto (클라이언트의 요청)

3. PagingDto (View에 보여지기 때문에 Response 패키지 아래 생성)

4. MainDto (Response패키지 아래 생성)

UpdateDto

package site.metacoding.red.web.dto.request.boards;

import lombok.Getter;

import lombok.Setter;

@Getter
@Setter
public class UpdateDto {// title,content
	private String title;
	private String content;
	
}

WriteDto

package site.metacoding.red.web.dto.request.boards;

import lombok.Getter;

import lombok.Setter;
import site.metacoding.red.domain.boards.Boards;

@Getter
@Setter

public class WriteDto {
	private String title;
	private String content;
	
	// 엔티티화 
	public Boards toEntity(Integer usersId) {
		Boards boards = new Boards(this.title, this.content, usersId);
		return boards;
	}
}

MainDto 

package site.metacoding.red.web.dto.response.boards;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class MainDto {
	private Integer id;
	private String title;
	private String username;

}

PagingDto

package site.metacoding.red.web.dto.response.boards;

import java.util.List;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class PagingDto {
	private boolean isNotResult;
	private String keyword;
	private Integer blockCount;// 한 블럭에서 페이지 갯수(5) 1-5, 6-10,
	private Integer currentBlock; // 현재 블럭 위치 1~5 , 다음 누르면 6~10 에 위치
	private Integer startPageNum;// 현재 블럭에서 시작 페이지 num
	private Integer lastPageNum; // 현재 블럭에서 마지막 페이지 num
	private Integer totalCount; // 전체 글의 수 
	private Integer totalPage; // 전체 페이지 수 
	private Integer currentPage; // 현재 페이지 
	private boolean isLast;
	private boolean isFirst;
	
	
	private List<MainDto> mainDtos;
	
	public void makeBlockInfo(String keyword) {
		this.keyword = keyword;
		this.blockCount = 5; // 검색을 해도 한 블럭에 페이지 갯수는 5
		this.currentBlock = currentPage / blockCount;
		this.startPageNum = 1 + blockCount * currentBlock;
		this.lastPageNum = 5+ blockCount * currentBlock;
		
		if(totalPage < lastPageNum) {
			this.lastPageNum = totalPage;
		}
		
	}

}

5. ApiController작성 후 테스트

Api는 View를 해줄 Controller를 만들기 전 데이터를 리턴해 제대로 동작하는지 확인 해주는 테스트해 줄 Controller역할

View가 아닌 데이터를 리턴 하기 때문에 @RestController 어노테이션 사용

package site.metacoding.red.web;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import site.metacoding.red.domain.boards.Boards;
import site.metacoding.red.domain.users.Users;
import site.metacoding.red.service.BoardsService;
import site.metacoding.red.service.UsersService;
import site.metacoding.red.web.dto.request.boards.UpdateDto;
import site.metacoding.red.web.dto.request.boards.WriteDto;
import site.metacoding.red.web.dto.response.boards.PagingDto;

@RequiredArgsConstructor
@RestController
public class BoardsApiController {

   private final HttpSession session;
   private final BoardsService boardsService;
   private final UsersService usersService;
   
   
   @PutMapping("/api/boards/{id}")
   public String update(@PathVariable Integer id, UpdateDto updateDto) {
      boardsService.게시글수정하기(id, updateDto);
      return "게시글수정완료";
   }

   @GetMapping("/api/boards/{id}/updateForm")
   public Boards updateForm(@PathVariable Integer id) {
      Boards boardsPS = boardsService.게시글상세보기(id);
      return boardsPS;
   }

   @DeleteMapping("/api/boards/{id}")
   public String deleteBoards(@PathVariable Integer id) {
      boardsService.게시글삭제하기(id);
      return "게시글삭제완료";
   }

   @PostMapping("/api/boards")
   public String writeBoards(WriteDto writeDto) {
      Users principal = (Users) session.getAttribute("principal");
      boardsService.게시글쓰기(writeDto, principal);
      return "게시글쓰기완료";
   }

   @GetMapping({ "/api", "/api/boards" })
   public PagingDto getBoardList(Integer page, String keyword) { // 0 -> 0, 1->10, 2->20
      PagingDto pagingDto = boardsService.게시글목록보기(page, keyword);
      return pagingDto;
   }

   @GetMapping("/api/boards/{id}")
   public Boards getBoardDetail(@PathVariable Integer id) {
      Boards boards = boardsService.게시글상세보기(id);
      return boards;
   }

}