Skip to content

[Spring 지하철 노선도 - 1,2단계] 기론(김규철) 미션 제출합니다. #191

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

Merged
merged 49 commits into from
May 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
4f7f121
docs : 기능 구현 요구사항 추가
jayjaehunchoi May 3, 2022
6128090
feat: 동일한 이름 등록시 에러가 발생한다.
jayjaehunchoi May 3, 2022
42d6ea5
refactor : validateDuplicateName 코드 분리
jayjaehunchoi May 3, 2022
798c650
feat : Line 등록 기능 추가
jayjaehunchoi May 3, 2022
984efe1
test: 중복 라인 중독시 에러발생 테스트 작성
jayjaehunchoi May 3, 2022
7f43877
feat: 전체 노선 조회 기능 추가
jayjaehunchoi May 3, 2022
f9bb7b3
feat : 노선 단건 조회 기능 추가
jayjaehunchoi May 3, 2022
3b9924f
feat: 노선 업데이트 기능 추가
jayjaehunchoi May 3, 2022
92edb79
feat : 노선 삭제 기능 추가
jayjaehunchoi May 3, 2022
863b410
refactor : test context를 최소화하도록 수정
jayjaehunchoi May 3, 2022
99ac14f
feat : database 관련 설정 추가
jayjaehunchoi May 3, 2022
92bc954
refactor
jayjaehunchoi May 3, 2022
9087e58
refactor: 전체 역 조회 jdbctemplate이용하여 수정
jayjaehunchoi May 3, 2022
8b0d071
feat : 역 삭제 쿼리 작성
jayjaehunchoi May 3, 2022
f853b03
feat: 역 등록기능 추가
jayjaehunchoi May 3, 2022
c19ea41
refactor : stationController save 코드 수정
jayjaehunchoi May 3, 2022
8220b3f
feat: 모든 역 조회 기능 구현
jayjaehunchoi May 3, 2022
e7c33d8
refactor: stationController findAll 코드 수정
jayjaehunchoi May 3, 2022
8968a00
feat : 역 삭제 기능 구현
jayjaehunchoi May 3, 2022
bb80722
refactor : stationController delete 코드 수정
jayjaehunchoi May 3, 2022
0375539
refactor : 레거시 코드 삭제
jayjaehunchoi May 3, 2022
ea1ce3e
refactor : schema 변경
jayjaehunchoi May 3, 2022
469d1ef
feat : 노선 저장 쿼리 추가
jayjaehunchoi May 4, 2022
826c50a
feat: 모든 노선 조회 쿼리 추가
jayjaehunchoi May 4, 2022
0b3f9f9
feat : 단건 노선 조회 쿼리 추가
jayjaehunchoi May 4, 2022
2e3d2ff
feat : 업데이트 쿼리 추가
jayjaehunchoi May 4, 2022
e0f10b8
feat : 삭제 쿼리 추가
jayjaehunchoi May 4, 2022
2641b69
refactor : repository 인터페이스 분리
jayjaehunchoi May 4, 2022
50699ef
feat : 노선 생성 기능 구현
jayjaehunchoi May 4, 2022
4081552
feat : 전체 노선 조회 기능 추가
jayjaehunchoi May 4, 2022
ae97955
feat : 이름으로 노선 조회 쿼리 추가
jayjaehunchoi May 4, 2022
25310f5
feat : 노선 명이 존재할 경우 예외 발생
jayjaehunchoi May 4, 2022
908135f
feat : 단건 노선 조회 기능 추가
jayjaehunchoi May 4, 2022
da6dc5b
feat : 업데이트 기능 추가
jayjaehunchoi May 4, 2022
88b66e3
feat : 삭제 기능 추가
jayjaehunchoi May 4, 2022
cad767d
refactor: 불필요한 코드 제거
Gyuchool May 6, 2022
ca9de3c
refactor: springBootTest에서 JdbcTest로 수정
Gyuchool May 6, 2022
21c064b
refactor: 생성자 체이닝 적용
Gyuchool May 6, 2022
79d0468
refactor: Optional을 반환하여 null처리문 제거
Gyuchool May 6, 2022
63b6bd6
refactor: dto에서 도메인으로 변환 로직 추가
Gyuchool May 6, 2022
87a1ed3
feat: 추가적인 예외 처리하도록 수정
Gyuchool May 6, 2022
7ec66ad
refactor: Map사용에서 request사용하도록 수정
Gyuchool May 6, 2022
3d76cc2
refactor: body도 검증하도록 수정
Gyuchool May 6, 2022
b941468
refactor: test코드에서 @Transactional 제거
Gyuchool May 6, 2022
31b6c88
refactor: 인수테스트 body도 검증하도록 수정
Gyuchool May 6, 2022
bbaeb36
refactor: 서버 예외 사항 추가
Gyuchool May 6, 2022
1b01580
refactor: 예외처리 메서드 네이밍 수정
Gyuchool May 6, 2022
2eba99f
refactor: 에러 처리 상태 코드 NotFound로 수정
Gyuchool May 6, 2022
339e7b3
refactor: 코드 포멧팅
Gyuchool May 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,19 @@
## 📝 License

This project is [MIT](https://github.com/woowacourse/atdd-subway-map/blob/master/LICENSE) licensed.


## 기능 구현 목록

- 지하철 역
- [x] 지하철역 생성 시 이미 등록된 이름으로 요청한다면 에러를 응답

- 지하철 노선
- [x] 동일한 노선 생성 불가
- api
- [x] post - /lines 등록 - name, color
- [x] get - /lines - List - id, name, color
- [ ] get - /lines/{id} - id, name, color
- [ ] put - /lines/{id} - name, color
- [ ] delete - /lines/{id}

6 changes: 3 additions & 3 deletions src/main/java/wooteco/subway/SubwayApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
@SpringBootApplication
public class SubwayApplication {

public static void main(String[] args) {
SpringApplication.run(SubwayApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(SubwayApplication.class, args);
}

}
23 changes: 23 additions & 0 deletions src/main/java/wooteco/subway/dao/LineRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package wooteco.subway.dao;

import wooteco.subway.domain.Line;

import java.util.List;
import java.util.Optional;

public interface LineRepository {

Line save(Line line);

List<Line> findAll();

Optional<Line> findById(Long id);

Optional<Line> findByName(String name);

void update(Long id, Line line);

void deleteById(Long id);

boolean existByName(String name);
}
102 changes: 102 additions & 0 deletions src/main/java/wooteco/subway/dao/LineRepositoryImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package wooteco.subway.dao;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import wooteco.subway.domain.Line;

import javax.sql.DataSource;
import java.util.List;
import java.util.Optional;

@Repository
public class LineRepositoryImpl implements LineRepository {

private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private final SimpleJdbcInsert simpleJdbcInsert;

private RowMapper<Line> rowMapper() {
return (resultSet, rowNum) -> {
long id = resultSet.getLong("id");
String name = resultSet.getString("name");
String color = resultSet.getString("color");
return new Line(id, name, color);
};
}

public LineRepositoryImpl(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
.withTableName("line")
.usingGeneratedKeyColumns("id");
}

@Override
public Line save(final Line line) {
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("name", line.getName())
.addValue("color", line.getColor());

long id = simpleJdbcInsert.executeAndReturnKey(parameters).longValue();
return new Line(id, line.getName(), line.getColor());
}

@Override
public List<Line> findAll() {
String sql = "SELECT * FROM line";
return namedParameterJdbcTemplate.query(sql, rowMapper());
}

@Override
public Optional<Line> findById(final Long id) {
String sql = "SELECT * FROM line WHERE id = :id";
SqlParameterSource parameters = new MapSqlParameterSource("id", id);
List<Line> lines = namedParameterJdbcTemplate.query(sql, parameters, rowMapper());
return getOptional(lines);
}

@Override
public Optional<Line> findByName(final String name) {
String sql = "SELECT * FROM line WHERE name = :name";
SqlParameterSource parameters = new MapSqlParameterSource("name", name);
List<Line> lines = namedParameterJdbcTemplate.query(sql, parameters, rowMapper());
return getOptional(lines);
}

private Optional<Line> getOptional(List<Line> lines) {
if (lines.isEmpty()) {
return Optional.empty();
}
return Optional.ofNullable(lines.get(0));
}

@Override
public void update(final Long id, final Line line) {
String sql = "UPDATE line SET name = :name, color = :color WHERE id = :id";

SqlParameterSource nameParameters = new MapSqlParameterSource()
.addValue("id", id)
.addValue("name", line.getName())
.addValue("color", line.getColor());

namedParameterJdbcTemplate.update(sql, nameParameters);
}

@Override
public void deleteById(Long id) {
String sql = "DELETE FROM line WHERE id = :id";
SqlParameterSource parameters = new MapSqlParameterSource("id", id);
namedParameterJdbcTemplate.update(sql, parameters);
}

@Override
public boolean existByName(String name) {
final String sql = "SELECT COUNT(*) FROM line WHERE name = :name";
SqlParameterSource parameters = new MapSqlParameterSource("name", name);
Integer count = namedParameterJdbcTemplate.queryForObject(sql, parameters, Integer.class);
return count != 0;
}
}
30 changes: 0 additions & 30 deletions src/main/java/wooteco/subway/dao/StationDao.java

This file was deleted.

21 changes: 21 additions & 0 deletions src/main/java/wooteco/subway/dao/StationRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package wooteco.subway.dao;

import wooteco.subway.domain.Station;

import java.util.List;
import java.util.Optional;

public interface StationRepository {

Station save(final Station station);

List<Station> findAll();

void deleteById(Long id);

Optional<Station> findByName(String name);

Optional<Station> findById(Long id);

boolean existByName(String name);
}
87 changes: 87 additions & 0 deletions src/main/java/wooteco/subway/dao/StationRepositoryImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package wooteco.subway.dao;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import wooteco.subway.domain.Station;

import javax.sql.DataSource;
import java.util.List;
import java.util.Optional;

@Repository
public class StationRepositoryImpl implements StationRepository {

private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private final SimpleJdbcInsert simpleJdbcInsert;

private RowMapper<Station> rowMapper() {
return (resultSet, rowNum) -> {
long id = resultSet.getLong("id");
String name = resultSet.getString("name");
return new Station(id, name);
};
}

public StationRepositoryImpl(DataSource dataSource) {
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
.withTableName("station")
.usingGeneratedKeyColumns("id");
}

@Override
public Station save(final Station station) {
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("name", station.getName());
Long id = simpleJdbcInsert.executeAndReturnKey(parameters).longValue();
return new Station(id, station.getName());
}

@Override
public List<Station> findAll() {
String sql = "SELECT * FROM station";
RowMapper<Station> stationRowMapper = rowMapper();
return namedParameterJdbcTemplate.query(sql, stationRowMapper);
}

@Override
public void deleteById(final Long id) {
String sql = "DELETE FROM station WHERE id = :id";
namedParameterJdbcTemplate.update(sql, new MapSqlParameterSource("id", id));
}

@Override
public Optional<Station> findByName(final String name) {
String sql = "SELECT * FROM station WHERE name = :name";
SqlParameterSource parameters = new MapSqlParameterSource("name", name);
List<Station> stations = namedParameterJdbcTemplate.query(sql, parameters, rowMapper());
return getOptional(stations);
}

@Override
public Optional<Station> findById(Long id) {
String sql = "SELECT * FROM station WHERE id = :id";
SqlParameterSource parameters = new MapSqlParameterSource("id", id);
List<Station> stations = namedParameterJdbcTemplate.query(sql, parameters, rowMapper());
return getOptional(stations);
}

private Optional<Station> getOptional(List<Station> stations) {
if (stations.isEmpty()) {
return Optional.empty();
}
return Optional.ofNullable(stations.get(0));
}

@Override
public boolean existByName(String name) {
final String sql = "SELECT COUNT(*) FROM station WHERE name = :name";
SqlParameterSource parameters = new MapSqlParameterSource("name", name);
Integer count = namedParameterJdbcTemplate.queryForObject(sql, parameters, Integer.class);
return count != 0;
}
}
45 changes: 45 additions & 0 deletions src/main/java/wooteco/subway/domain/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package wooteco.subway.domain;

import java.util.Objects;

public class Line {

private final Long id;
private final String name;
private final String color;

public Line(String name, String color) {
this(null, name, color);
}

public Line(Long id, String name, String color) {
this.id = id;
this.name = name;
this.color = color;
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getColor() {
return color;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Line line = (Line) o;
return Objects.equals(name, line.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}
}
Comment on lines +32 to +45
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

동등성의 기준을 name으로 잡으셨군요. 그렇다면 id는 어떤 역할을 할까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그 전에 1단계에서 dao 클래스에서 static List<Line> lines 와 같은 형태로 Line들을 저장하는 역할을 하는 상수가 있었습니다. 이 때, 들어오는 Line들마다 구별해주기 위해서 name을 기준으로 구별을 해주는데 이용했습니다.

그런데 현재는 db에 pk값으로 id를 자동으로 auto_increment 해주기 때문에 이를 통해서 식별할 수 있도록 되었습니다!

name은 unique이고 id는 pk이기 때문에 null을 허용하지 않는 id를 이용해서 식별하도록 하는 게 좋다고 생각합니다!

26 changes: 19 additions & 7 deletions src/main/java/wooteco/subway/domain/Station.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
package wooteco.subway.domain;

import java.util.Objects;

public class Station {
private Long id;
private String name;
private final Long id;
private final String name;

public Station() {
public Station(String name) {
this(null, name);
}

public Station(Long id, String name) {
this.id = id;
this.name = name;
}

public Station(String name) {
this.name = name;
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Station station = (Station) o;
return Objects.equals(name, station.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}
}

Loading