본문 바로가기

과제를하면서 트러블슈팅

일정 관리 앱 만들기

반응형
SMALL

안녕하세요 다들 설연휴 잘지내셧나요? 저는 설연휴동안 공부도하고 친할머니 뵈러 갔다왔습니다 ㅎㅎ

이번에는 일정 관리 앱 만들기를 해봣는데요 

어휴,..너무어렵더라고요 검색을 엄청많이 했던거같습니다.. 강의에서 배운거를 거의 배끼는 수준이였네요,,ㅎㅎ

package org.example.scheduling_app.controller;

import org.example.scheduling_app.Service.ScheduleService;
import org.example.scheduling_app.dto.ScheduleRequestDto;
import org.example.scheduling_app.dto.ScheduleResponseDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/schedules")
public class ScheduleController {

    private final ScheduleService scheduleService;

    public ScheduleController(ScheduleService scheduleService) {
        this.scheduleService = scheduleService;
    }

    //HTTP POST 요청을 처리하는 메서드
    @PostMapping
    //SchduleService의 createSchedule 메서드를 호출하여 일정을 생성
    public ResponseEntity<ScheduleResponseDto> createSchdule(@RequestBody ScheduleRequestDto dto){
        // 클라이언트로부터 받은 DTO를 바탕으로 일정 생성
        ScheduleResponseDto response = scheduleService.createSchedule(dto);
        //SchduleResponseDto로 응답을 반환, 응답상태는 201로 설정
        return new ResponseEntity<>(response, HttpStatus.CREATED);
    }
    // 전체 일정 조회
    @GetMapping
    public ResponseEntity<List<ScheduleResponseDto>> findAllSchedules() {
        // 모든 일정을 조회하여 리스트로 반환
        List<ScheduleResponseDto> schedules = scheduleService.getAllSchedules();

        // 성공적인 조회 후, HTTP 200 상태 코드와 함께 전체 일정 반환
        return ResponseEntity.ok(schedules);
    }
    @GetMapping("/{id}")
    public ResponseEntity<ScheduleResponseDto> findScheduleById(@PathVariable Long id) {
        // 선택한 일정 조회
        ScheduleResponseDto scheduleResponse = scheduleService.getScheduleById(id);
        return ResponseEntity.ok(scheduleResponse);
    }
    // 일정 수정
    @PutMapping("/{id}")
    public ResponseEntity<ScheduleResponseDto> updateSchedule(
            @PathVariable Long id,  // URL 경로에서 일정 ID를 받음
            @RequestBody ScheduleRequestDto dto) {  // 요청 바디에서 수정할 항목들을 받음
        ScheduleResponseDto response = scheduleService.updateSchedule(id, dto);
        return ResponseEntity.ok(response);  // 수정된 일정 정보를 HTTP 200 응답으로 반환
    }
    // 일정 삭제
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteSchedule(
            @PathVariable Long id,  // URL 경로에서 일정 ID를 받음
            @RequestParam String password) {  // 요청 파라미터에서 비밀번호를 받음
        try {
            scheduleService.deleteSchedule(id, password);
            return ResponseEntity.noContent().build();  // 성공적으로 삭제된 경우 204 No Content 응답
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();  // 비밀번호가 일치하지 않으면 403 Forbidden 응답
        }
    }
}
package org.example.scheduling_app.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.format.annotation.DateTimeFormat;

@Getter
@AllArgsConstructor
public class ScheduleRequestDto {
    private String task; //할일
    private String author; //작성자명
    private String password;//비밀번호
}
package org.example.scheduling_app.dto;


import lombok.AllArgsConstructor;
import lombok.Getter;
import org.example.scheduling_app.entity.Schedule;

import java.time.format.DateTimeFormatter;


@Getter
@AllArgsConstructor
public class ScheduleResponseDto {
    private Long id;
    private String task;
    private String author;
    private String createdAt;
    private String updatedAt;

    // DateTimeFormatter 사용하여 포맷 지정
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

    public ScheduleResponseDto(Schedule schedule) {
        this.id = schedule.getId();
        this.task = schedule.getTask();
        this.author = schedule.getAuthor();
        this.createdAt = schedule.getCreatedAt().format(formatter); // createdAt 포맷
        this.updatedAt = schedule.getUpdatedAt().format(formatter); // updatedAt 포맷
    }
}
package org.example.scheduling_app.entity;

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


import java.time.LocalDateTime;

@Getter
@Setter
@AllArgsConstructor

public class Schedule {
    private Long id;
    private String task;
    private String author;
    private String password;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    //생성자
    public Schedule(String task, String author, String password, LocalDateTime createdAt) {
        this.task = task;
        this.author = author;
        this.password = password;
        this.createdAt = createdAt;
        this.updatedAt = createdAt;//최초작성시,수정일은 작성일과 동일하다
    }

    //일정 수정 메서드
    public void update(String task,String password){
        this.task=task;
        this.password=password;
        this.updatedAt=LocalDateTime.now();//수정시 현재 시간으로 업데이트
    }
    // 작성자명 수정 메서드
    public void setAuthor(String author) {
        this.author = author;
    }

    // 수정일 갱신 메서드
    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }
}
package org.example.scheduling_app.repository;

import org.example.scheduling_app.dto.ScheduleResponseDto;
import org.example.scheduling_app.entity.Schedule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class ScheduleRepository {

    private final JdbcTemplate jdbcTemplate;

    // JdbcTemplate을 생성자 주입 방식으로 받아옵니다.
    public ScheduleRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // 일정 저장 메서드
    public ScheduleResponseDto saveSchedule(Schedule schedule) {
        // 일정 저장을 위한 SQL 쿼리 (createdAt과 updatedAt은 LocalDateTime 값)
        String query = "INSERT INTO schedule (task, author, password, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)";
        jdbcTemplate.update(query, schedule.getTask(), schedule.getAuthor(), schedule.getPassword(), schedule.getCreatedAt(), schedule.getUpdatedAt());

        // 최근 생성된 ID를 가져옵니다.
        Long id = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);

        // 생성된 ID와 함께 응답을 위한 DTO를 반환합니다.
        return new ScheduleResponseDto(id, schedule.getTask(), schedule.getAuthor(), schedule.getCreatedAt().toString(), schedule.getUpdatedAt().toString());
    }
    // 모든 일정 조회 메소드
    public List<Schedule> findAllSchedules() {
        // 모든 일정 정보를 조회하는 쿼리
        String sql = "SELECT * FROM schedule";
        return jdbcTemplate.query(sql, (rs, rowNum) ->
                new Schedule(
                        rs.getLong("id"),
                        rs.getString("task"),
                        rs.getString("author"),
                        rs.getString("password"),
                        rs.getTimestamp("createdAt").toLocalDateTime(),
                        rs.getTimestamp("updatedAt").toLocalDateTime()
                )
        );
    }
    // 일정 조회 메서드 (선택한 일정 단건)
    public Schedule findScheduleById(Long id) {
        String sql = "SELECT * FROM schedule WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) ->
                new Schedule(
                        rs.getLong("id"),
                        rs.getString("task"),
                        rs.getString("author"),
                        rs.getString("password"),
                        rs.getTimestamp("createdAt").toLocalDateTime(),
                        rs.getTimestamp("updatedAt").toLocalDateTime()
                )
        );
    }
    // 일정 삭제
    public void deleteSchedule(Long id) {
        // 일정 삭제를 위한 SQL 쿼리
        String sql = "DELETE FROM schedule WHERE id = ?";
        jdbcTemplate.update(sql, id);
    }

}
package org.example.scheduling_app.Service;

import org.example.scheduling_app.dto.ScheduleRequestDto;
import org.example.scheduling_app.dto.ScheduleResponseDto;
import org.example.scheduling_app.entity.Schedule;
import org.example.scheduling_app.repository.ScheduleRepository;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ScheduleService {

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
    String formattedDate = LocalDateTime.now().format(formatter);
    private final ScheduleRepository scheduleRepository;

    public ScheduleService(ScheduleRepository scheduleRepository) {
        this.scheduleRepository = scheduleRepository;
    }

    public ScheduleResponseDto createSchedule(ScheduleRequestDto dto) {
        //Schedule 엔티티 객체 생성
        Schedule schedule = new Schedule(dto.getTask(), dto.getAuthor(), dto.getPassword(), LocalDateTime.parse(formattedDate, formatter));
        //데이터베이스에 저장하고 응답을 반환
        return scheduleRepository.saveSchedule(schedule);
    }


    // 모든 일정 조회 메소드
    public List<ScheduleResponseDto> getAllSchedules() {
        // DB에서 모든 일정 목록을 조회하고 DTO로 변환하여 반환
        return scheduleRepository.findAllSchedules()
                .stream()
                .map(ScheduleResponseDto::new)
                .collect(Collectors.toList());
    }

    public ScheduleResponseDto getScheduleById(Long id) {
        // 선택한 일정 조회
        Schedule schedule = scheduleRepository.findScheduleById(id);
        return new ScheduleResponseDto(schedule);
    }

    // 일정 수정
    public ScheduleResponseDto updateSchedule(Long id, ScheduleRequestDto dto) {
        // 기존 일정 조회
        Schedule existingSchedule = scheduleRepository.findScheduleById(id);

        // 비밀번호 검증
        if (!existingSchedule.getPassword().equals(dto.getPassword())) {
            throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
        }
        // 수정할 항목 갱신
        existingSchedule.update(dto.getTask(), dto.getPassword()); // 할일과 비밀번호 수정
        existingSchedule.setAuthor(dto.getAuthor()); // 작성자명 수정
        existingSchedule.setUpdatedAt(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)); // 수정일을 현재 시간으로 갱신

        // 수정된 일정 저장 후, 응답용 DTO 반환
        return scheduleRepository.saveSchedule(existingSchedule);
    }
    // 일정 삭제
    public void deleteSchedule(Long id, String password) {
        // 기존 일정 조회
        Schedule existingSchedule = scheduleRepository.findScheduleById(id);

        // 비밀번호 검증
        if (!existingSchedule.getPassword().equals(password)) {
            throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
        }

        // 일정 삭제
        scheduleRepository.deleteSchedule(id); // 삭제 메서드 호출
    }
}

 

우선 제가만든 코드들인데요

이것을 만들면서 있던 시행착오를 알려드리겟습니다.

 

조건은 위와같았는데요

우선 강의에서 거의 봣던것들이라 거의 쉬웟는데 

전체일정조회,선택일정조회까진 그냥 잘됫던거같습니다

그런데

이렇게 비밀번호와 작성자를 입력하고 sand를 누르면

이렇게해서 일정생성에 성공했죠

그후 전체일정 조회인데요

이렇게 만들어지는걸보실수있으시죠

그후 선택일정조회인데요 위와같이 잘나오는걸 볼수있었습니다.

근데 이렇게 쓰면서 생각해보니 저시간이 처음에 좀 문제가있었습니다.

시간이 16:10:16.9328747 이런식으로 나오는겁니다

그래서 아 이렇게 나오면  안되겟다 16:10:16으로 끊기게끔 만들어보자 하고 뭐가있을까

검색해보니

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

이런식으로 초까지만 나오게끔 포멧을 하면 된다고 하더라고요

그래서 위와같이시간이 잘나오게됫습니다.

그후

선택한일정수정인데요

이렇게 패스워드가 맞아야 수정되는걸 보실수가있는데요

createdAt을보면 처음 id값을 만든시간

updatedAt을보면 수정시간 인걸 보실수있습니다.

그리고일정삭제

위와같이 비밀번호를 입력해줘야

이렇게삭제되며

잘못된 비밀번호를 입력시 오류나는걸 보실수 있습니다. 봐주셔서감사합니다.

반응형
LIST

'과제를하면서 트러블슈팅' 카테고리의 다른 글

일정 관리 앱 만들기 devlop  (0) 2025.02.13
키오스크 만들기 Lv5  (2) 2025.01.20
키오스크 만들기 Lv4  (0) 2025.01.17
키오스크 만들기 Lv3  (0) 2025.01.16
키오스크 만들기  (3) 2025.01.15