[문제]
분명히 Key 값으로 name을 넣었는데도 결과는 일정 목록을 조회할 때와 별반 다르지 않았다. 차라리 400이나 500번 대 오류 메시지가 떴다면 원인이 뭔지 금방 찾을 수 있으나, 200 OK 메시지가 뜨면 코드를 다시 읽어야 했다. 우선 수정한 부분을 다시 읽었다.
[원인]
package com.spring.weekthree.repository;
import com.spring.weekthree.dto.PlanResponseDto;
import com.spring.weekthree.entity.Plan;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import org.springframework.web.server.ResponseStatusException;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
// Data Access Layer(Repository Layer)
@Repository
public class JdbcTemplatePlanRepository implements PlanRepository {
private final JdbcTemplate jdbcTemplate;
public JdbcTemplatePlanRepository(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public PlanResponseDto save(Plan plan) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("planner").usingGeneratedKeyColumns("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", plan.getName());
parameters.put("password", plan.getPassword());
parameters.put("plannedDate", plan.getPlannedDate());
parameters.put("title", plan.getTitle());
parameters.put("task", plan.getTask());
parameters.put("createdDateTime", plan.getCreatedDateTime());
parameters.put("updatedDateTime", plan.getUpdatedDateTime());
Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
return new PlanResponseDto(
key.longValue(),
plan.getName(),
plan.getPlannedDate(),
plan.getTitle(),
plan.getTask(),
plan.getCreatedDateTime(),
plan.getUpdatedDateTime());
}
@Override
public List<PlanResponseDto> fetchAllPlans(String name, LocalDate updatedDate) {
Stream<PlanResponseDto> allPlans = Stream.empty();
if (name != null) {
allPlans = jdbcTemplate.queryForStream(
"SELECT * FROM planner " +
"WHERE BINARY name = ? " +
"ORDER BY updatedDateTime DESC",
plannerRowMapper(),
name
);
}
allPlans = jdbcTemplate.queryForStream(
"SELECT * FROM planner " +
"ORDER BY updatedDateTime DESC",
plannerRowMapper()
);
/*
[오답] else문 안에 넣지 않음
[정답] else문 안에 넣어야 함
*/
return allPlans.collect(Collectors.toList());
}
@Override
public Plan fetchPlanById0rElseThrow(Long id) {
List<Plan> result = jdbcTemplate.query(
"SELECT * FROM planner WHERE id =?",
plannerRowMapperEach(),
id
);
return result.stream()
.findAny()
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
"Id does no exist id = " + id)
);
}
@Override
public void updatePatchInRepository(
Long id,
String name,
LocalDate plannedDate,
String title,
String task
) {
jdbcTemplate.update(
"UPDATE planner SET " +
"name = ?, " +
"plannedDate = ?, " +
"title = ?, " +
"task = ?, " +
"updatedDateTime = CURRENT_TIMESTAMP " +
"WHERE id = ?",
name,
plannedDate,
title,
task,
id
);
}
@Override
public void deletePlan(Long id) {
jdbcTemplate.update("DELETE FROM planner WHERE id = ?",
id
);
}
private RowMapper<PlanResponseDto> plannerRowMapper() {
return new RowMapper<PlanResponseDto>() {
@Override
public PlanResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
return new PlanResponseDto(
rs.getLong("id"),
rs.getString("name"),
rs.getDate("plannedDate").toLocalDate(),
rs.getString("title"),
rs.getString("task"),
rs.getTimestamp("createdDateTime").toLocalDateTime(),
rs.getTimestamp("updatedDateTime").toLocalDateTime()
);
}
};
}
private RowMapper<Plan> plannerRowMapperEach() {
return new RowMapper<Plan>() {
@Override
public Plan mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Plan(
rs.getLong("id"),
rs.getString("name"),
rs.getString("password"),
rs.getDate("plannedDate").toLocalDate(),
rs.getString("title"),
rs.getString("task"),
rs.getTimestamp("createdDateTime").toLocalDateTime(),
rs.getTimestamp("updatedDateTime").toLocalDateTime()
);
}
};
}
}
원인은 짐작한 대로 if문만 쓰고 else문을 쓰지 않은 데에 있었다. 설령 작성자 이름에 해당하는 name이 null이 아니어서 if문이 실행돼도 다시 값이 덮어씌워져 목록 전체가 조회되었다.
[해결]
package com.spring.weekthree.repository;
import com.spring.weekthree.dto.PlanResponseDto;
import com.spring.weekthree.entity.Plan;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import org.springframework.web.server.ResponseStatusException;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
// Data Access Layer(Repository Layer) 수정하기
@Repository
public class JdbcTemplatePlanRepository implements PlanRepository {
private final JdbcTemplate jdbcTemplate;
public JdbcTemplatePlanRepository(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public PlanResponseDto save(Plan plan) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("planner").usingGeneratedKeyColumns("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", plan.getName());
parameters.put("password", plan.getPassword());
parameters.put("plannedDate", plan.getPlannedDate());
parameters.put("title", plan.getTitle());
parameters.put("task", plan.getTask());
parameters.put("createdDateTime", plan.getCreatedDateTime());
parameters.put("updatedDateTime", plan.getUpdatedDateTime());
Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
return new PlanResponseDto(
key.longValue(),
plan.getName(),
plan.getPlannedDate(),
plan.getTitle(),
plan.getTask(),
plan.getCreatedDateTime(),
plan.getUpdatedDateTime());
}
@Override
public List<PlanResponseDto> fetchAllPlans(String name, LocalDate updatedDate) {
Stream<PlanResponseDto> allPlans = Stream.empty();
if (name != null) {
allPlans = jdbcTemplate.queryForStream(
"SELECT * FROM planner " +
"WHERE BINARY name = ? " +
"ORDER BY updatedDateTime DESC",
plannerRowMapper(),
name
);
} else {
allPlans = jdbcTemplate.queryForStream(
"SELECT * FROM planner " +
"ORDER BY updatedDateTime DESC",
plannerRowMapper()
);
}
/*
[수정 전]
allPlans = jdbcTemplate.queryForStream(
"SELECT * FROM planner " +
"ORDER BY updatedDateTime DESC",
plannerRowMapper()
);
*/
return allPlans.collect(Collectors.toList());
}
@Override
public Plan fetchPlanById0rElseThrow(Long id) {
List<Plan> result = jdbcTemplate.query(
"SELECT * FROM planner WHERE id =?",
plannerRowMapperEach(),
id
);
return result.stream()
.findAny()
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND,
"Id does no exist id = " + id)
);
}
@Override
public void updatePatchInRepository(
Long id,
String name,
LocalDate plannedDate,
String title,
String task
) {
jdbcTemplate.update(
"UPDATE planner SET " +
"name = ?, " +
"plannedDate = ?, " +
"title = ?, " +
"task = ?, " +
"updatedDateTime = CURRENT_TIMESTAMP " +
"WHERE id = ?",
name,
plannedDate,
title,
task,
id
);
}
@Override
public void deletePlan(Long id) {
jdbcTemplate.update("DELETE FROM planner WHERE id = ?",
id
);
}
private RowMapper<PlanResponseDto> plannerRowMapper() {
return new RowMapper<PlanResponseDto>() {
@Override
public PlanResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
return new PlanResponseDto(
rs.getLong("id"),
rs.getString("name"),
rs.getDate("plannedDate").toLocalDate(),
rs.getString("title"),
rs.getString("task"),
rs.getTimestamp("createdDateTime").toLocalDateTime(),
rs.getTimestamp("updatedDateTime").toLocalDateTime()
);
}
};
}
private RowMapper<Plan> plannerRowMapperEach() {
return new RowMapper<Plan>() {
@Override
public Plan mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Plan(
rs.getLong("id"),
rs.getString("name"),
rs.getString("password"),
rs.getDate("plannedDate").toLocalDate(),
rs.getString("title"),
rs.getString("task"),
rs.getTimestamp("createdDateTime").toLocalDateTime(),
rs.getTimestamp("updatedDateTime").toLocalDateTime()
);
}
};
}
}
개인 프로젝트를 진행할수록 코드 길이가 눈에 띄게 늘어나서 이런 실수 하나하나도 그냥 넘어갈 수가 없다. 당장 기록하기 귀찮다고 넘어갔다가 훗날 얼마나 큰 눈덩이가 되어 돌아올지 모르는 만큼, 챗GPT에도 이것저것 물어보고 몇 번씩 POSTMAN을 써서 확인했다. 잘 해결되어서 다행이다.
'Troubleshooting: 무엇이 문제였는가? > 일정 관리 앱 만들기' 카테고리의 다른 글
2단계: "PATCH를 두 번 눌러야 수정이 돼요. 왜 이럴까요?" (0) | 2024.12.09 |
---|---|
1단계: "넌 띄어쓰기를 소중히 하지 않았어" (0) | 2024.12.09 |
2단계: "왜 수정 날짜를 수정하려고 하니!" (0) | 2024.12.08 |
1단계: "@NoArgsConstructor가 굴린 대형 눈덩이" (0) | 2024.12.08 |
2단계: "500 Internal Server Error라니! 일단 침착해!" (0) | 2024.12.07 |