tuter77

게시판 만들기(11) - 작업내용 수정. 본문

GroupStudy

게시판 만들기(11) - 작업내용 수정.

tuter77 2023. 1. 29. 20:49

● 기존 healthInfo View에 CRUD 구현 수정.

 

▷ Entity를 DTO로

 

기존의 엔티티를 통해 데이터를 전달하는 방식을 완전 수정했다. 

View와 컨트롤러, 서비스 간에 데이터를 교환할 때 엔티티 자체로 수정하고 보내는 것이아니라 DTO에 값을 저장해서 DTO에 Setter를 구현해 값을 주고받는 형태로 변환했다. 

 

- homeController

@RequiredArgsConstructor
@Controller
@Slf4j
public class HomeController {
    private final HealthRepository healthRepository;
    private final HomeService homeService;


    //기본형태 사용안함.
    @GetMapping("/home") //url localhost:8080/home
    public String home(Model model) {
        model.addAttribute("list", healthRepository.findAll());
        return "home";

    }
    //상세페이지
    @GetMapping("/home/view")
    public String homeRead(Model model,@RequestParam Long id){
        HealthResponseDTO dto = homeService.healthView(id);
        List<ReviewResponseDTO> reviews = dto.getReviews();
        // 리뷰
        if(reviews != null && !reviews.isEmpty()){
            model.addAttribute("reviews", reviews);
        }
        // homeService.updateView(id); //view에 추가하는 기능
        model.addAttribute("healthInfo", dto);
        return "healthview";
    }
    // 저장 페이지.
    @GetMapping("/save")
    public String writeView(){
        return "save";
    }

    //저장 기능 구현.
    @PostMapping("/home/save")
    // requestDTO에 Setter를 열어서 form데이터 바인딩.
    public String homeSave(HealthRequestDTO healthRequestDTO){
        homeService.saveHealth(healthRequestDTO);

        return "redirect:/page"; //prg패턴.
    }

    //삭제기능.
    @GetMapping("/home/delete")
    public String healthDelete(@RequestParam Long id){
        homeService.healthDelete(id);
        return "redirect:/page";
    }

    //상세 페이지 내 수정페이지 보여주기
    @GetMapping("/home/modified")
    public String modifiedView(@RequestParam Long id, Model model) {
        model.addAttribute(HealthResponseDTO
                .toEntity(homeService.healthView(id)));
        return "modified";
    }


    //상세 페이지 내 수정 기능
    @PostMapping("/home/modified/update")
    public String homeModified(HealthRequestDTO healthRequestDTO) {
            homeService.updateHealth(healthRequestDTO);
        return "redirect:/page";
    }

    @GetMapping("/page")
    public String pageHome(Model model, Pageable pageable) {

        Page<HealthInfo> healthInfoPage = homeService.healthList(pageable);
        model.addAttribute("pages",healthInfoPage);
        model.addAttribute("maxPage",5);

        return "page";
    }

}

요청하는 데이터, 즉 클라이언트가 저장, 수정 기능을 구현하기 위해 입력하는 데이터들은 모두 HealthRequestDTO에 저장한다. 

이 데이터는 DB에 저장되기 위해 toEntity라는 HealthRequestDTO클래스의 메서드를 이용하여 엔티티인 HealthInfo 타입으로 변환된다.

 

이 DTO타입으로 각 값들을 가져오기 위해 조언받은 input 태그의 hidden 타입을 이용했다.(뒤에 html 파일에서 살펴보겠다.)

 

- Service 

public interface HomeService {

        public boolean saveHealth(HealthRequestDTO healthRequestDTO);
        public List<HealthInfo> HealthList();
        public HealthResponseDTO healthView(Long id) ;
        public boolean updateHealth(HealthRequestDTO healthRequestDTO);

        public boolean healthDelete(Long id);
        Page<HealthInfo> healthList(Pageable pageable);
}
@Service
@RequiredArgsConstructor
public class HomeServiceImpl implements HomeService {

        private final HealthRepository healthRepository;


    @Override //home에 리스트형식으로 다 찾아오기
    public List<HealthInfo> HealthList() {
        List<HealthInfo>list=healthRepository.findAll();
        return list;
    }

    @Override //상세페이지 보여주기
    public HealthResponseDTO healthView(Long id) {
        HealthInfo healthInfo = healthRepository.findById(id).orElseThrow(IllegalArgumentException::new);
        return HealthResponseDTO.builder()
                .id(healthInfo.getId())
                .brand_name(healthInfo.getBrand_name())
                .category(healthInfo.getCategory())
                .land_number(healthInfo.getLand_number())
                .road_number(healthInfo.getRoad_number())
                .build();
    }

    @Override //저장기능
        public boolean saveHealth(HealthRequestDTO healthRequestDTO) {
        healthRepository.save(healthRequestDTO.toEntity(healthRequestDTO));
        return false;
    }

    @Override
    public boolean updateHealth(HealthRequestDTO healthRequestDTO){
        HealthInfo healthInfo = healthRepository.findById(healthRequestDTO.getId()).orElseThrow(RuntimeException::new);
        System.out.println(healthInfo.getId());

        healthInfo.modifyHealthInfo(healthRequestDTO.getBrand_name()
                ,healthRequestDTO.getCategory()
                ,healthRequestDTO.getLand_number()
                ,healthRequestDTO.getRoad_number());

        healthRepository.save(healthInfo);

        return false;
    }

        @Override //삭제기능
        public boolean healthDelete(@RequestParam Long id){
        healthRepository.deleteById(id);
        return true;
        }

    @Override
    public Page<HealthInfo> healthList(Pageable pageable){
            return healthRepository.findAll(pageable);

    }
}

DB는 레포지토리와 데이터를 주고받고 Service는 컨트롤러에서 전달받은 데이터를 레포지토리에 전달한다.

때문에 healthRepository의 메서드를 사용하는것은 모두 여기서 구현했다.

 

저장하기 위한 기존의 write.html 파일은 이름만 save로 바꾸었고, 내부 코드은 동일하다.

id값을 healthInfo 엔티티에서 자동을 배정해주기 위해서이다.

다만 상세페이지 view와 수정페이지 view의 경우, 읽어서 view에 값을 뿌려주는 기능을 DTO로 받아야해서 안에 id를 hidden 타입으로 선언했다.

 

- 상세페이지 view(healthview.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>상세페이지</title>
</head>

<body>
    <form>
        <input type="hidden" th:name="id" th:value="${healthInfo.id}"></input>
        <h1 th:text="${healthInfo.brand_name}"></h1>
        <p th:text="${healthInfo.category}"></p>
        <p th:text="${healthInfo.land_number}"></p>
        <p th:text="${healthInfo.road_number}"></p>
        <a th:href="@{/home/modified(id=${healthInfo.id})}">수정</a>
        <a th:href="@{/home/delete(id=${healthInfo.id})}">삭제</a>
        <a th:href="@{/review(id=${healthInfo.id})}">리뷰 보기</a>
        <button type="submit" onclick="location.href='/page'">뒤로</button>
    </form>
</body>
</html>

DTO타입으로 바인딩하기 위해 기존에 없던 form태그를 활용한 것과 input 태그 내에 id값을 hidden으로 선언해 DTO의 모든 밸류가 다 입력 되어주도록 하고 있다.

 

- 수정 페이지(modified.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>상세페이지</title>
</head>

<body>
    <form th:action="@{/home/modified/update}" method="post">
        <input name="id" type ="hidden" th:value="${healthInfo.id}">
        <input name="brand_name" type ="text" th:value="${healthInfo.brand_name}">
        <input name="category" type ="text" th:value="${healthInfo.category}">
        <input name="land_number" type ="text" th:value="${healthInfo.land_number}">
        <input name="road_number" type ="text" th:value="${healthInfo.road_number}">
        <button type="submit">수정</button>
        <a th:href="@{/page}">홈으로</a>
    </form>
</body>
</html>

기존에 id값을 @Pathvariable로 받던것을 빼고 form 데이터를 DTO로 바인딩하여 id값조회를 getId를 통해 DTO내에서 이루어지도록 하고있다. 

이 과정에서 @RequestBody를 이용하고 싶었지만 아쉽게도 Ajax의 Json타입이어야 유효했다.

때문에 매개변수로 바인딩 된 DTO를 받고있다.

 

이전에 DTO도 뭔지모르겠고 어떻게 이용할지 id 값은 왜 안넘어가는지 뭐가 문제인지 찾지도 못한 입장으로서 지금은 작은 한걸음을 나아갔다고 느껴 정말 뿌듯하다.

 

다만, 아직 해야할 review시리즈가있으니 고삐를 놓지말자. 

 

위 내용은 2023.01.20에 공부한 내용입니다.