-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[1단계 - 지하철 정보 관리 기능] 조이(김성연) 미션 제출합니다. #54
Changes from 9 commits
171ff4a
a9bf07f
0adff23
917ca85
c27d3df
a3a691b
245839a
1528b1b
c27a38a
ba249ed
7b15531
1be28e6
d691518
b238c01
f9b5713
26f518d
9cfd39e
4b4e86e
4afa981
f0db060
5f267fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,24 @@ | ||
# jwp-subway-path | ||
# jwp-subway-path | ||
|
||
## 요구 사항 | ||
### API 기능 요구사항 | ||
- [x] 노선에 역 등록 API 신규 구현 | ||
- [x] 노선에 역 제거 API 신규 구현 | ||
- [x] 노선 조회 API | ||
- [x] 노선 포함된 역 목록 조회 API 수정 | ||
- [x] 노선에 포함된 역을 순서대로 보여주도록 응답을 개선합니다. | ||
|
||
|
||
## 기능 목록 | ||
- [x] 노선에 역을 등록한다. | ||
- [x] 노선에 역을 등록할 때 거리 정보도 계산한다. | ||
- [ ] 거리 정보는 양의 정수로 제한 | ||
- [x] 노선 가운데 역이 등록 될 경우 거리 정보를 새롭게 계산해야 한다. | ||
- [x] 노선 가운데 역이 등록 될 경우, 가능한 거리를 초과한 경우 예외를 발생시킨다. | ||
- [ ] 최초 등록 시 한 역만 등록하려는 경우 예외를 발생시킨다. | ||
|
||
- [x] 노선에서 역을 제거한다. | ||
- [x] 노선에서 역이 제거될 경우 역과 역 사이의 거리도 재배정되어야 한다. | ||
- [x] 노선에서 역을 제거할 경우 정상 동작을 위해 재배치 되어야 한다. | ||
- [x] 노선에 등록된 역이 2개 인 경우 하나의 역을 제거할 때 두 역이 모두 제거되어야 한다. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package subway.application; | ||
|
||
import java.util.List; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import subway.dao.LineDao; | ||
import subway.dao.SectionDao; | ||
import subway.dao.StationDao; | ||
import subway.domain.Direction; | ||
import subway.domain.Section; | ||
import subway.domain.Sections; | ||
import subway.domain.Station; | ||
import subway.dto.SectionRequest; | ||
|
||
@Transactional | ||
@Service | ||
public class SectionService { | ||
private final StationDao stationDao; | ||
private final SectionDao sectionDao; | ||
private final LineDao lineDao; | ||
|
||
public SectionService(final StationDao stationDao, final SectionDao sectionDao, final LineDao lineDao) { | ||
this.stationDao = stationDao; | ||
this.sectionDao = sectionDao; | ||
this.lineDao = lineDao; | ||
} | ||
|
||
public long addSection(final long lineId, SectionRequest request) { | ||
validateLineId(lineId); | ||
Station requestUpStation = findVerifiedStationByName(request.getUpStationName()); | ||
Station requestDownStation = findVerifiedStationByName(request.getDownStationName()); | ||
|
||
Sections sections = sectionDao.findSectionsByLineId(lineId); | ||
|
||
Section requestedSection = new Section(requestUpStation, requestDownStation, request.getDistance()); | ||
|
||
if (sections.isInitialSave()) { | ||
return sectionDao.save(requestedSection, lineId); | ||
} | ||
if (sections.isDownEndAppend(requestedSection)) { | ||
long savedSectionId = sectionDao.save(requestedSection, lineId); | ||
Section downEndSection = sections.getDownEndSection(); | ||
sectionDao.updateNextSection(savedSectionId, downEndSection.getId()); | ||
return savedSectionId; | ||
} | ||
if (sections.isUpEndAppend(requestedSection)) { | ||
Section upEndSection = sections.getUpEndSection(); | ||
Section newSection = new Section(requestUpStation, requestDownStation, request.getDistance(), | ||
upEndSection.getNextSectionId()); | ||
return sectionDao.save(newSection, lineId); | ||
} | ||
|
||
Section includeSection = sections.getIncludeSection(requestedSection); | ||
Direction direction = includeSection.checkDirection(requestedSection); | ||
if (direction == Direction.INNER_LEFT) { | ||
Section innerRight = new Section(requestedSection.getDownStation(), includeSection.getDownStation(), | ||
includeSection.getDistance() - requestedSection.getDistance(), | ||
includeSection.getNextSectionId()); | ||
|
||
long savedId = sectionDao.save(innerRight, lineId); | ||
|
||
Section innerLeft = new Section(includeSection.getId(), requestedSection.getUpStation(), | ||
requestedSection.getDownStation(), requestedSection.getDistance(), savedId); | ||
|
||
sectionDao.update(innerLeft); | ||
return savedId; | ||
} | ||
|
||
Section innerRight = new Section(requestedSection.getUpStation(), requestedSection.getDownStation(), | ||
requestedSection.getDistance(), includeSection.getNextSectionId()); | ||
long savedId = sectionDao.save(innerRight, lineId); | ||
|
||
Section innerLeft = new Section(includeSection.getId(), includeSection.getUpStation(), | ||
requestedSection.getUpStation(), | ||
includeSection.getDistance() - requestedSection.getDistance(), | ||
savedId); | ||
sectionDao.update(innerLeft); | ||
return savedId; | ||
} | ||
|
||
public void removeStation(long stationId, long lineId) { | ||
Sections sections = sectionDao.findSectionsByLineId(lineId); | ||
|
||
validateStationInLine(stationId, sections); | ||
|
||
// 역이 2개 남았을 때 | ||
if (sections.size() == 1) { | ||
sectionDao.deleteByLineId(lineId); | ||
} | ||
// 상행 종점일 때 | ||
if (sections.getUpEndSection().isSameUpStationId(stationId)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. get하지 않고 바로 물어볼 수 있을 것 같아요~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수정하였습니다! |
||
sectionDao.deleteSectionByUpStationId(stationId, lineId); | ||
return; | ||
} | ||
// 하행 종점일 때 | ||
Section downEndSection = sections.getDownEndSection(); | ||
if (downEndSection.isSameDownStationId(stationId)) { | ||
Section section = sections.findSectionByNextSection(downEndSection); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 동일하게 변경해보면 좋겠네요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수정하였습니다! |
||
sectionDao.deleteSectionByDownStationId(stationId, lineId); | ||
sectionDao.updateNextSection(null, section.getId()); | ||
return; | ||
} | ||
Section innerRight = sections.findSectionByUpStation(stationId); | ||
Section innerLeft = sections.findSectionByDownStation(stationId); | ||
Section newSection = new Section(innerLeft.getId(), innerLeft.getUpStation(), innerRight.getDownStation(), | ||
innerLeft.getDistance() + innerRight.getDistance(), | ||
innerRight.getNextSectionId()); | ||
sectionDao.update(newSection); | ||
sectionDao.deleteById(innerRight.getId()); | ||
} | ||
|
||
private void validateStationInLine(final long stationId, final Sections sections) { | ||
if (sections.isNotExistStation(stationId)) { | ||
throw new IllegalArgumentException("해당 노선에 존재하지 않는 역입니다."); | ||
} | ||
} | ||
|
||
public Sections findAllByLindId(long lineId) { | ||
return sectionDao.findSectionsByLineId(lineId); | ||
} | ||
|
||
public List<Station> findSortedAllStationsByLindId(long lineId) { | ||
Sections sections = sectionDao.findSectionsByLineId(lineId); | ||
return sections.getSortedStations(); | ||
} | ||
|
||
private void validateLineId(long lineId) { | ||
if (!lineDao.existsById(lineId)) { | ||
throw new IllegalArgumentException("존재하지 않는 호선입니다."); | ||
} | ||
} | ||
|
||
private Station findVerifiedStationByName(String name) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어떤 의도의 네이밍일까요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Station Name을 통해 Station을 찾고 없으면 생성하여 반환해주고자 하였습니다. |
||
if(!stationDao.existsByName(name)) { | ||
return stationDao.insert(new Station(name)); | ||
} | ||
|
||
return stationDao.findByName(name); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package subway.dao; | ||
|
||
import java.util.List; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.jdbc.core.RowMapper; | ||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; | ||
import org.springframework.jdbc.core.namedparam.SqlParameterSource; | ||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert; | ||
import org.springframework.stereotype.Repository; | ||
import subway.domain.Section; | ||
import subway.domain.Sections; | ||
import subway.domain.Station; | ||
|
||
@Repository | ||
public class SectionDao { | ||
|
||
private final JdbcTemplate jdbcTemplate; | ||
private final SimpleJdbcInsert simpleJdbcInsert; | ||
|
||
public SectionDao(final JdbcTemplate jdbcTemplate) { | ||
this.jdbcTemplate = jdbcTemplate; | ||
this.simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate) | ||
.withTableName("SECTIONS") | ||
.usingGeneratedKeyColumns("id"); | ||
} | ||
|
||
public Sections findSectionsByLineId(final long lineId) { | ||
|
||
String sql = "SELECT SEC.id, S1.id, S1.name, S2.id, S2.name, SEC.distance, SEC.next_id" | ||
+ " FROM SECTIONS AS SEC " | ||
+ " JOIN STATION AS S1 ON SEC.up_id = S1.id " | ||
+ " JOIN STATION AS S2 ON SEC.down_id = S2.id " | ||
+ " WHERE SEC.line_id = ?"; | ||
|
||
List<Section> sections = jdbcTemplate.query(sql, upStationMapper(), lineId); | ||
|
||
return new Sections(lineId, sections); | ||
} | ||
|
||
private RowMapper<Section> upStationMapper() { | ||
return (rs, rowNum) -> new Section( | ||
rs.getLong(1), | ||
new Station(rs.getLong(2), rs.getString(3)), | ||
new Station(rs.getLong(4), rs.getString(5)), | ||
rs.getInt(6), | ||
rs.getLong(7)); | ||
} | ||
|
||
public long save(final Section section, final long lineId) { | ||
SqlParameterSource sqlParameterSource = new MapSqlParameterSource() | ||
.addValue("id", section.getId()) | ||
.addValue("up_id", section.getUpStationId()) | ||
.addValue("down_id", section.getDownStationId()) | ||
.addValue("distance", section.getDistance()) | ||
.addValue("line_id", lineId) | ||
.addValue("next_id", section.getNextSectionId()); | ||
|
||
return simpleJdbcInsert.executeAndReturnKey(sqlParameterSource).longValue(); | ||
} | ||
|
||
public void updateNextSection(Long nextId, long sectionId) { | ||
String sql = "UPDATE SECTIONS SET next_id = ? WHERE id = ?"; | ||
jdbcTemplate.update(sql, nextId, sectionId); | ||
} | ||
|
||
public void update(final Section section) { | ||
String sql = "UPDATE SECTIONS SET up_id = ?, down_id = ?, distance = ?, next_id = ? WHERE id = ?"; | ||
jdbcTemplate.update(sql, | ||
section.getUpStationId(), | ||
section.getDownStationId(), | ||
section.getDistance(), | ||
section.getNextSectionId(), | ||
section.getId()); | ||
} | ||
|
||
public void deleteById(final long sectionId) { | ||
String sql = "delete SECTIONS where id = ?"; | ||
jdbcTemplate.update(sql, sectionId); | ||
} | ||
|
||
public void deleteSectionByUpStationId(final long stationId, final long lineId) { | ||
String sql = "delete SECTIONS where up_id = ? AND line_id = ?"; | ||
jdbcTemplate.update(sql, stationId, lineId); | ||
} | ||
|
||
public void deleteSectionByDownStationId(final long stationId, final long lineId) { | ||
String sql = "delete SECTIONS where down_id = ? AND line_id = ?"; | ||
jdbcTemplate.update(sql, stationId, lineId); | ||
} | ||
|
||
public void deleteByLineId(long lineId) { | ||
String sql = "delete SECTIONS where line_id = ?"; | ||
jdbcTemplate.update(sql, lineId); | ||
} | ||
|
||
public Section findById(long sectionId) { | ||
String sql = "SELECT SEC.id, S1.id, S1.name, S2.id, S2.name, SEC.distance, SEC.next_id" | ||
+ " FROM SECTIONS AS SEC " | ||
+ " JOIN STATION AS S1 ON SEC.up_id = S1.id " | ||
+ " JOIN STATION AS S2 ON SEC.down_id = S2.id " | ||
+ " WHERE SEC.id = ?"; | ||
|
||
return jdbcTemplate.queryForObject(sql, upStationMapper(), sectionId); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
메서드를 분리해볼까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
기존에 SectionService의 로직 분리가 어렵다고 느껴 전체 구조를 변경해보았습니다!
수정하면서 메서드 분리도 함께 진행하였습니다.
감사합니다!