개발로드

☆KDT 2024-04-29프로젝트★(3)-BackEnd-SpringBoot-gradle 본문

JAVA

☆KDT 2024-04-29프로젝트★(3)-BackEnd-SpringBoot-gradle

위대한개발자 2024. 4. 30. 13:32

TodoServiceImpl 생성


package com.shopapi.service;


import com.shopapi.domain.Todo;
import com.shopapi.dto.TodoDTO;
import com.shopapi.repository.TodoRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@Transactional
@Log4j2
@RequiredArgsConstructor  //생성자 자동 주입
public class TodoServiceImpl implements TodoService{

    //자동 주입 대상은 final
    private final ModelMapper modelMapper;
    private final TodoRepository todoRepository;


    //#1. 등록(insert)
    @Override
    public Long register(TodoDTO todoDTO) {

        log.info("등록!!! .........");

        Todo todo = modelMapper.map(todoDTO, Todo.class);

        Todo savedTodo = todoRepository.save(todo);

        return savedTodo.getTno();

    }


    //#2. 조회(select)
    @Override
    public TodoDTO get(Long tno) {

        Optional<Todo> result = todoRepository.findById(tno);

        Todo todo = result.orElseThrow();

        TodoDTO dto = modelMapper.map(todo, TodoDTO.class);

        return dto;
    }

    //#3. 업데이트(update)
    @Override
    public void modify(TodoDTO todoDTO) {

        Optional<Todo> result = todoRepository.findById(todoDTO.getTno());

        Todo todo = result.orElseThrow();

        todo.changeTitle(todoDTO.getTitle());
        todo.changeDueDate(todoDTO.getDueDate());
        todo.changeComplete(todoDTO.isComplete());

        todoRepository.save(todo);

    }

    //#4. 삭제(delete)
    @Override
    public void remove(Long tno) {

        todoRepository.deleteById(tno);

    }

}

 

 

Optional 


Optional<Todo> result = todoRepository.findById(tno);
//Optional : 래퍼 클래스
//  이것을 사용하지 않으면 매번 if 문을 이용해 null 인지 체크한 후 사용
//  이것을 이용하면 null 체크를 위한 if 문 없이도 NullPointerException 이 발생하지 않음

 

TodoServiceImpl   register 메소드 test


package com.shopapi.service;

import com.shopapi.domain.Todo;
import com.shopapi.dto.TodoDTO;
import com.shopapi.repository.TodoRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDate;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
@Log4j2
class TodoServiceImplTest {

    @Autowired
    private TodoService todoService;

    @Test
    @DisplayName("등록 테스트")
    public void testRegister() {

    TodoDTO todoDTO = TodoDTO.builder()
            .title("서비스 테스트1")
            .writer("홍길동")
            .dueDate(LocalDate.of(2024, 04, 30))
            .build();

    Long tno = todoService.register(todoDTO);
    log.info("서비스 테스트 결과 : " + tno);

    }//end of method

}//end of class

 

 

스트림(stream)


//  데이터 소스를 추상화하고, 데이터를 다루는데 자주 사용되는 메소드들을 정의해 놓음
//  데이터 소스를 추상화 - 데이터 소스가 무엇이던 간에 같은 방식으로 다룰 수 있게
//  만들어 놓은 것, 코드의 재사용성이 높아짐
//  스트림을 이용하면 배열이나 컬렉션 뿐만 아니라 파일에 저장된 데이터도 모두
//  같은 방식으로 다룰 수 있음
//  단, 한번 사용하면 닫혀서 다시 사용할 수 없음. 필요하다면 스트림을 다시 생성해야 함
//  스트림은 데이터 소스를 변경하지 않는다. 데이터 소스로부터 데이터를 읽기만 할 뿐
//  정렬된 결과를 컬렉션이나 배열에 담아서 반환할 수 있음
//  List<String> sortList = strStream.sorted().collect(Collectors.toList());

 

 

PageRequestDTO 작성


package com.shopapi.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
public class PageRequestDTO {

    @Builder.Default
    private int page = 1;

    @Builder.Default
    private int size = 10;

}

 

 

PageResponseDTO 작성


package com.shopapi.dto;

import lombok.Builder;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

//PageResponseDTO 는 나중에 다른 타입의 DTO 들을 이용할 수 있도록 제네릭 타입으로 작성
//PageResponseDTO 는 DTO 의 리시트와 전체 데이터의 수를 지정하면 페이지 처리에 필요한 번호나 이전/다음에 대한 처리를 함

@Data
public class PageResponseDTO<E> {

    private List<E> dtoList;

    private List<Integer> pageNumList;

    private PageRequestDTO pageRequestDTO;

    private boolean prev, next;

    private int totalCount, prevPage, nextPage, totalPage, current;

    @Builder(builderMethodName = "withAll")
    public PageResponseDTO(List<E> dtoList, PageRequestDTO pageRequestDTO, long totalCount) {

        this.dtoList = dtoList;
        this.pageRequestDTO = pageRequestDTO;
        this.totalCount = (int)totalCount;

        int end =   (int)(Math.ceil( pageRequestDTO.getPage() / 10.0 )) *  10;

        int start = end - 9;

        int last =  (int)(Math.ceil((totalCount/(double)pageRequestDTO.getSize())));

        end =  end > last ? last: end;

        this.prev = start > 1;


        this.next =  totalCount > end * pageRequestDTO.getSize();

        this.pageNumList = IntStream.rangeClosed(start,end).boxed().collect(Collectors.toList());

        if(prev) {
            this.prevPage = start -1;
        }

        if(next) {
            this.nextPage = end + 1;
        }

        this.totalPage = this.pageNumList.size();

        this.current = pageRequestDTO.getPage();

    }
}