코트카타
35) 부족한 금액 계산하기
class Solution {
public long solution(int price, int money, int count) {
long answer = -1;
long total = 0;
for (int i = 1; i <= count ; i++) {
total += (long)price * i;
}
if(money < total){
answer = total-money;
} else {
answer = 0;
}
return answer;
}
}
한 개 정도 테스트에서 틀리는 부분이 있어서
오버플로우 문제인가 생각하고,
if-else문도 넣어주었다.
다른 분들의 풀이
class Solution {
public long solution(long price, long money, long count) {
return Math.max(price * (count * (count + 1) / 2) - money, 0);
}
}
출처:https://school.programmers.co.kr/learn/courses/30/lessons/82612/solution_groups?language=java
스탠다드반 세션
[Spring 5기] 면접 단골 질문 ! DI, IoC란 무엇일까?
핵심 개념
- IoC: 객체의 생성과 관리 주체를 개발자가 아닌 컨테이너(Spring)가 담당.
- DI: 의존성을 외부에서 주입받아 객체 간 결합도를 낮춤.
DI와 IoC의 장점
- 코드의 유연성 증가.
- 유지보수성 향상.
- 테스트 용이성 개선(Mock 객체 사용 가능).
일정관리 과제
도전
Lv 4. 페이지네이션
중복된 매핑
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'scheduleController' method com.example.schedule.presentation.controller.ScheduleController#findAllSchedule(LocalDate, Long) to {GET [/schedules]}: There is already 'scheduleController' bean method
같은 주소로 같은 메서드가 중복 매핑되어서 발생한 예외이다.
@GetMapping("/page")
페이지네이션 부분을 위의 주소에서 실행하도록 수정하니 정상적으로 작동하였다.
limit, offset 이용해서 페이징 처리하기
SELECT s.scheduleId, s.todo, w.writerId, w.name, s.createdAt, s.updatedAt
FROM schedule s
JOIN writer w
ON s.writerId = w.writerId
ORDER BY s.updatedAt DESC
LIMIT 5 OFFSET 0
먼저 해당하는 sql문을 먼저 작성했다.
@GetMapping("/page")
public ResponseEntity<List<ScheduleResponseDto>> findAllSchedulePaging(
@RequestParam(value="pageNo", defaultValue="1") int pageNo,
@RequestParam(value="pageNo", defaultValue="10") int pageSize) {
log.info("pageNo={}", pageNo);
log.info("pageSize={}", pageSize);
return ResponseEntity.ok(scheduleService.findAllSchedulePaging(pageNo,pageSize));
}
컨트롤러에서 페이지 번호와 페이지 크기를 각각 pageNo, pageSize 파라미터로 받아왔다.
offset 값을 구하는 공식을 노트에 정리하면서 스스로 구했다.(아래 이미지 참조)
@Override
public List<ScheduleResponseDto> findAllSchedulePaging(int pageNo, int pageSize) {
String sql = "SELECT s.scheduleId, s.todo, w.writerId, w.name, s.createdAt, s.updatedAt\n" +
"FROM schedule s\n" +
"JOIN writer w\n" +
"ON s.writerId = w.writerId\n" +
"ORDER BY s.updatedAt DESC\n" +
"LIMIT ? OFFSET ?";
int offsetValue = (pageNo-1) * pageSize;
return jdbcTemplate.query(sql,scheduleRowMapper(),pageSize,offsetValue);
}
따라서 위와 같은 코드가 완성되었다.
+ 튜터님께서 자바에서 제공하는 객체인 Pageable에 대해 알려주셨다.
추후 이에 대해 적용할 예정이다.
Lv 5. 예외 발생 처리
수정, 삭제 시 요청할 때 보내는 비밀번호가 일치하지 않을 때 예외가 발생
먼저, 구상한 계획은 아래와 같다.
일정관리 레파지토리 - update 메서드
- scheduleId에 해당하는 password를 DB에서 받아오기(dbPassword)- dbPassword와 requestBody에서 입력 받은 비밀번호 일치여부 확인
- 불일치 시 return -1
일정관리 서비스 - update 메서드
- 만약 -1이면 비밀번호 불일치 관련 예외처리 발생
그러나 튜터님께서 update 메서드에는 update 관련 내용만 있고,
비밀번호를 검증하는 부분에 대한 메서드를 분리하는 것을 제안하셔서 분리했다.
@Override
public int updateSchedule(Long scheduleId, String todo, String password) {
return jdbcTemplate.update("UPDATE schedule SET todo = ?,updatedAt = NOW()" +
"WHERE scheduleId = ? AND password = ?",todo, scheduleId, password);
}
@Override
public String validatePassword(Long scheduleId) {
return jdbcTemplate.queryForObject("select password from schedule where scheduleId =?", String.class, scheduleId);
}
@Override
public int deleteSchedule(Long scheduleId, String password) {
return jdbcTemplate.update("delete from schedule where scheduleId=? and password=?",scheduleId,password);
}
@Transactional
@Override
public ScheduleResponseDto updateSchedule(Long scheduleId, String todo, String password) {
if (todo == null || password == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The todo, writer and password are required values.");
}
String dbPassword = scheduleRepository.validatePassword(scheduleId);
if (!dbPassword.equals(password)){
throw new ApplicationException(ErrorMessageCode.BAD_REQUEST,
List.of(new ApiError("password", "비밀번호가 일치하지 않습니다.")));
}
int updatedRow = scheduleRepository.updateSchedule(scheduleId, todo, password);
if (updatedRow == 0) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + scheduleId);
}
Schedule schedule = scheduleRepository.findScheduleByIdOrElseThrow(scheduleId);
return new ScheduleResponseDto(schedule);
}
@Transactional
@Override
public void deleteSchedule(Long scheduleId, String password) {
if (password == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The password are required values.");
}
String dbPassword = scheduleRepository.validatePassword(scheduleId);
if (!dbPassword.equals(password)){
throw new ApplicationException(ErrorMessageCode.BAD_REQUEST,
List.of(new ApiError("password", "비밀번호가 일치하지 않습니다.")));
}
int deletedRow = scheduleRepository.deleteSchedule(scheduleId, password);
if (deletedRow == 0) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + scheduleId);
}
}
Lv 6. null 체크 및 특정 패턴에 대한 검증 수행
Entity가 아닌 reqestDto에 관련 어노테이션 추가
@Getter
public class ScheduleRequestDto {
@Size(max = 200)
@NotEmpty
private String todo;
private Long writerId;
@NotEmpty
private String password;
}
위와 같이 해야 200자 이내 입력과 필수값 처리가 가능하다.
+ 추후 리팩토링 사항
Repository에서 DTO가 아닌 entity 사용하도록 수정
이는 입문 단계에서 필수는 아니므로 시간적 여유가 있다면 할 것이다.
아직 다 하지는 못했지만
일단 도전 과제를 모두 도전하고자 한다.
월요일에는 남은 과제를 도전하고, 리팩토링 및 문서 정리할 계획이다.
'CODING > 스파르타 내일배움캠프 TIL' 카테고리의 다른 글
32_문자열 내림차순으로 배치하기_일정관리 과제 Lv 3 구현완료_25.1.27(월) (0) | 2025.01.27 |
---|---|
31_약수의 개수와 덧셈_일정관리 과제 Lv 1,2 구현완료_25.1.24(금) (0) | 2025.01.24 |
30_내적_키오스크 과제 피드백_Spring 입문 6주차_일정관리 과제 Lv 0,1 구현중_25.1.23(목) (1) | 2025.01.23 |
29_수박수박수박수박수박수?_스탠다드 Spring 3 Layered, Spring MVC_Spring 입문 4,5주차_25.1.22(수) (0) | 2025.01.22 |
28_가운데 글자 가져오기_Spring 입문_25.1.21(화) (0) | 2025.01.21 |