-
Notifications
You must be signed in to change notification settings - Fork 306
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
E2e step2 #877
base: jaejeong1
Are you sure you want to change the base?
E2e step2 #877
Changes from 4 commits
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 |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package subway.line; | ||
|
||
import lombok.Getter; | ||
|
||
import javax.persistence.*; | ||
|
||
@Entity | ||
@Getter | ||
public class Line { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
private String name; | ||
private String color; | ||
|
||
public Line() {} | ||
|
||
public Line(String name, String color) { | ||
this.name = name; | ||
this.color = color; | ||
} | ||
|
||
public void update(String name, String color) { | ||
this.name = name; | ||
this.color = color; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package subway.line; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.net.URI; | ||
import java.util.List; | ||
|
||
@RestController | ||
public class LineController { | ||
private final LineService lineService; | ||
|
||
public LineController(LineService lineService) { | ||
this.lineService = lineService; | ||
} | ||
|
||
@GetMapping("/lines") | ||
public ResponseEntity<List<LineResponse>> showLines() { | ||
return ResponseEntity.ok().body(lineService.findAllLines()); | ||
} | ||
|
||
@PostMapping("/lines") | ||
public ResponseEntity<LineResponse> createLine(@RequestBody LineRequest lineRequest) { | ||
LineResponse line = lineService.saveLine(lineRequest); | ||
return ResponseEntity.created(URI.create("/lines/" + line.getId())).body(line); | ||
} | ||
|
||
@GetMapping("/lines/{id}") | ||
public ResponseEntity<LineResponse> showLine(@PathVariable Long id) { | ||
return ResponseEntity.ok().body(lineService.findLineById(id)); | ||
} | ||
|
||
@PutMapping("/lines/{id}") | ||
public ResponseEntity<Void> updateLine(@PathVariable Long id, @RequestBody LineRequest lineRequest) { | ||
lineService.updateLine(id, lineRequest); | ||
return ResponseEntity.ok().build(); | ||
} | ||
|
||
@DeleteMapping("/lines/{id}") | ||
public ResponseEntity<Void> deleteLine(@PathVariable Long id) { | ||
lineService.deleteLineById(id); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package subway.line; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface LineRepository extends JpaRepository<Line, Long> { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package subway.line; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
public class LineRequest { | ||
private String name; | ||
private String color; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package subway.line; | ||
|
||
import lombok.Getter; | ||
import subway.station.Station; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
public class LineResponse { | ||
private Long id; | ||
private String name; | ||
private String color; | ||
|
||
public LineResponse(Long id, String name, String color) { | ||
this.id = id; | ||
this.name = name; | ||
this.color = color; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package subway.line; | ||
|
||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
public class LineService { | ||
private LineRepository lineRepository; | ||
|
||
public LineService(LineRepository lineRepository) { | ||
this.lineRepository = lineRepository; | ||
} | ||
|
||
@Transactional | ||
public LineResponse saveLine(LineRequest lineRequest) { | ||
Line line = lineRepository.save(new Line(lineRequest.getName(), lineRequest.getColor())); | ||
return createLineResponse(line); | ||
} | ||
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. API 스펙을 미션 요구사항에 맞게 변경하면 아마 LineService의 로직들이 조금 더 복잡해질 거예요. 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. Builder 패턴 적용해 Line 엔티티 생성 과정의 유연성을 확보했습니다! |
||
|
||
public List<LineResponse> findAllLines() { | ||
return lineRepository.findAll().stream() | ||
.map(this::createLineResponse) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public LineResponse findLineById(Long id) { | ||
return createLineResponse(lineRepository.findById(id).orElseThrow(IllegalArgumentException::new)); | ||
} | ||
|
||
@Transactional | ||
public void updateLine(Long id, LineRequest lineRequest) { | ||
Line line = lineRepository.findById(id).orElseThrow(IllegalArgumentException::new); | ||
line.update(lineRequest.getName(), lineRequest.getColor()); | ||
} | ||
|
||
@Transactional | ||
public void deleteLineById(Long id) { | ||
lineRepository.deleteById(id); | ||
} | ||
|
||
private LineResponse createLineResponse(Line line) { | ||
return new LineResponse( | ||
line.getId(), | ||
line.getName(), | ||
line.getColor() | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
package subway; | ||
package subway.station; | ||
|
||
import subway.line.Line; | ||
|
||
import javax.persistence.*; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package subway; | ||
package subway.station; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package subway; | ||
package subway.station; | ||
|
||
public class StationRequest { | ||
private String name; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package subway; | ||
package subway.station; | ||
|
||
public class StationResponse { | ||
private Long id; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package subway; | ||
|
||
import io.restassured.RestAssured; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.boot.test.web.server.LocalServerPort; | ||
import org.springframework.test.context.ActiveProfiles; | ||
|
||
import static io.restassured.RestAssured.UNDEFINED_PORT; | ||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; | ||
|
||
@SpringBootTest(webEnvironment = RANDOM_PORT) | ||
@ActiveProfiles("acceptance") | ||
public abstract class AcceptanceTest { | ||
|
||
@LocalServerPort | ||
protected int port; | ||
|
||
@Autowired | ||
private DatabaseCleanup databaseCleanup; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
if (RestAssured.port == UNDEFINED_PORT) { | ||
RestAssured.port = port; | ||
databaseCleanup.afterPropertiesSet(); | ||
} | ||
databaseCleanup.execute(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package subway; | ||
|
||
import com.google.common.base.CaseFormat; | ||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.EntityManager; | ||
import javax.persistence.PersistenceContext; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
@Service | ||
@Profile("acceptance") | ||
public class DatabaseCleanup implements InitializingBean{ | ||
@PersistenceContext | ||
private EntityManager entityManager; | ||
private List<String> tableNames; | ||
@Override | ||
public void afterPropertiesSet() { | ||
tableNames = entityManager.getMetamodel().getEntities().stream() | ||
.filter(e -> e.getJavaType().getAnnotation(Entity.class) != null) | ||
.map(e -> CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, e.getName())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
@Transactional | ||
public void execute() { | ||
// 쓰기 지연 저장소에 남은 SQL을 마저 수행 | ||
entityManager.flush(); | ||
// 연관 관계 맵핑된 테이블이 있는 경우 참조 무결성을 해제해줘야 Trancate 가능 | ||
entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate(); | ||
Comment on lines
+29
to
+34
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. cleanup 잘 만들어 주셨네요. 👍 |
||
|
||
for (String tableName : tableNames) { | ||
// 테이블 이름 순회하며 Trancate SQL 수행 | ||
entityManager.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate(); | ||
// 테이블의 내부가 지워지면 그 다음부터는 ID값을 다시 1부터 시작할 수 있도록 기본 값 초기화 | ||
entityManager.createNativeQuery("ALTER TABLE " + tableName + " ALTER COLUMN " | ||
+ "ID RESTART WITH 1").executeUpdate(); | ||
} | ||
entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate(); | ||
} | ||
} |
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.
미션 요구사항과 다른 스펙으로 구현되어 있어요. 😭
LineController의 다른 부분들도 미션에서 요구하는 스펙에 맞게 변경해 주세요!
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.
가장 중요한 요구사항 구현에 미스가 있었군요.. 참고해서 수정해보겠습니다! 감사합니다 :)