-
Notifications
You must be signed in to change notification settings - Fork 0
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
박자스동터차 경주 2단계 #8
base: main
Are you sure you want to change the base?
Changes from 18 commits
227e10f
479dd33
fa3f081
11d31ed
314f00d
6a0e142
95f6855
ca7c8d6
06abb19
ce71dda
1e63c66
ce96d76
6ba3533
39d4e46
1b31c3c
c4a600c
35f4996
068f395
578e675
06b0608
e886c52
a5de3c2
04bb0d8
7fada27
6fda343
f7d899e
3b99dd9
9cf0152
dcf1b6d
ea55c02
d46221c
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,20 +1,23 @@ | ||
plugins { | ||
id 'java' | ||
id 'org.springframework.boot' version '2.7.9' | ||
id 'io.spring.dependency-management' version '1.0.15.RELEASE' | ||
id 'java' | ||
id 'org.springframework.boot' version '2.7.9' | ||
id 'io.spring.dependency-management' version '1.0.15.RELEASE' | ||
} | ||
|
||
sourceCompatibility = '11' | ||
|
||
repositories { | ||
mavenCentral() | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
implementation 'org.springframework.boot:spring-boot-starter-jdbc' | ||
runtimeOnly 'com.h2database:h2' | ||
testImplementation 'io.rest-assured:rest-assured:4.4.0' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
} | ||
|
||
tasks.named('test') { | ||
useJUnitPlatform() | ||
useJUnitPlatform() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package racingcar; | ||
|
||
import java.util.Comparator; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
import racingcar.controller.RacingConsoleController; | ||
import racingcar.dao.CarDao; | ||
import racingcar.dao.RacingGameDao; | ||
import racingcar.dao.entity.CarEntity; | ||
import racingcar.dao.entity.RacingGameEntity; | ||
import racingcar.service.RacingGameService; | ||
|
||
public class RacingCarConsoleApplication { | ||
public static void main(String[] args) { | ||
RacingGameService racingGameService = new RacingGameService(new InnerCarDao(), new InnerRacingGameDao()); | ||
RacingConsoleController racingConsoleController = new RacingConsoleController(racingGameService); | ||
racingConsoleController.run(); | ||
} | ||
|
||
static class InnerCarDao implements CarDao { | ||
private final Map<Long, CarEntity> database = new HashMap<>(); | ||
private Long key = 1L; | ||
|
||
@Override | ||
public void saveAll(List<CarEntity> racingCars) { | ||
for (CarEntity racingCar : racingCars) { | ||
database.put(key, racingCar); | ||
key++; | ||
} | ||
} | ||
|
||
@Override | ||
public List<CarEntity> findByRacingGameId(Long id) { | ||
return database.values().stream() | ||
.filter(carEntity -> Objects.equals(carEntity.getGameId(), id)) | ||
.collect(Collectors.toList()); | ||
} | ||
} | ||
|
||
static class InnerRacingGameDao implements RacingGameDao { | ||
private final Map<Long, RacingGameEntity> database = new HashMap<>(); | ||
private Long id = 1L; | ||
|
||
@Override | ||
public Long save(RacingGameEntity racingGameEntity) { | ||
database.put(id, racingGameEntity); | ||
id++; | ||
return id - 1; | ||
} | ||
|
||
@Override | ||
public List<RacingGameEntity> findAllByCreatedTimeAsc() { | ||
return database.values() | ||
.stream().sorted(Comparator.comparing(RacingGameEntity::getCreatedTime)) | ||
.collect(Collectors.toList()); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package racingcar.controller; | ||
|
||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
|
||
@RestControllerAdvice | ||
public class ControllerAdvice { | ||
|
||
@ExceptionHandler | ||
public ResponseEntity<String> handleValidationExceptions(RuntimeException e) { | ||
return ResponseEntity.internalServerError().body(e.getMessage()); | ||
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. e.getMessage()를 통해 runtimeException 같은거를 잡게 되면 너무 많은 정보가 돌아갈 수 있어서 |
||
} | ||
|
||
@ExceptionHandler | ||
public ResponseEntity<String> handleValidationExceptions(IllegalArgumentException e) { | ||
return ResponseEntity.badRequest().body(e.getMessage()); | ||
} | ||
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. 어떤 예외를 잡는건지 명시해주면 좋을 것 같아요 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package racingcar.controller; | ||
|
||
import racingcar.dto.RacingGameRequest; | ||
import racingcar.dto.RacingGameResponse; | ||
import racingcar.service.RacingGameService; | ||
import racingcar.view.InputView; | ||
import racingcar.view.OutputView; | ||
|
||
public class RacingConsoleController { | ||
|
||
private final RacingGameService racingGameService; | ||
|
||
public RacingConsoleController(RacingGameService racingGameService) { | ||
this.racingGameService = racingGameService; | ||
} | ||
|
||
public void run() { | ||
String names = InputView.inputNames(); | ||
int count = InputView.inputTryCount(); | ||
RacingGameRequest racingGameRequest = new RacingGameRequest(names, count); | ||
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. web 에서 사용되는 것 같은 request 나 response 가 |
||
|
||
RacingGameResponse racingGameResponse = racingGameService.play(racingGameRequest); | ||
|
||
OutputView.printRacing(racingGameResponse.getRacingCars()); | ||
OutputView.printWinners(racingGameResponse.getWinners()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package racingcar.controller; | ||
|
||
import java.util.List; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import racingcar.dto.RacingGameRequest; | ||
import racingcar.dto.RacingGameResponse; | ||
import racingcar.service.RacingGameService; | ||
|
||
@RestController | ||
public class RacingGameController { | ||
private final RacingGameService racingGameService; | ||
|
||
public RacingGameController(RacingGameService racingGameService) { | ||
this.racingGameService = racingGameService; | ||
} | ||
|
||
@PostMapping("/plays") | ||
public ResponseEntity<RacingGameResponse> play(@RequestBody RacingGameRequest racingGameRequest) { | ||
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. @valid 어노테이션 써봐도 좋을듯 |
||
RacingGameResponse response = racingGameService.play(racingGameRequest); | ||
return ResponseEntity.ok(response); | ||
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. http code 201이 더 어울리긴 하네 |
||
} | ||
|
||
@GetMapping("/plays") | ||
public ResponseEntity<List<RacingGameResponse>> playHistory() { | ||
List<RacingGameResponse> history = racingGameService.findHistory(); | ||
return ResponseEntity.ok(history); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package racingcar.dao; | ||
|
||
import java.util.List; | ||
import racingcar.dao.entity.CarEntity; | ||
|
||
public interface CarDao { | ||
|
||
void saveAll(List<CarEntity> racingCars); | ||
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. saveAll 이 void 이고, RacingGameDao 에서는 Long 이라서 통일성이 떨어지는 느낌 |
||
|
||
List<CarEntity> findByRacingGameId(Long id); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package racingcar.dao; | ||
|
||
import java.sql.PreparedStatement; | ||
import java.sql.SQLException; | ||
import java.util.List; | ||
import org.springframework.jdbc.core.BatchPreparedStatementSetter; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.stereotype.Component; | ||
import racingcar.dao.entity.CarEntity; | ||
|
||
@Component | ||
public class CarJdbcDao implements CarDao { | ||
|
||
private final JdbcTemplate jdbcTemplate; | ||
|
||
public CarJdbcDao(JdbcTemplate jdbcTemplate) { | ||
this.jdbcTemplate = jdbcTemplate; | ||
} | ||
|
||
@Override | ||
public void saveAll(List<CarEntity> racingCars) { | ||
String sql = "INSERT INTO CAR (name, position, is_win, racing_game_id) VALUES (?, ?, ?, ?)"; | ||
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { | ||
@Override | ||
public void setValues(PreparedStatement ps, int i) throws SQLException { | ||
CarEntity carEntity = racingCars.get(i); | ||
ps.setString(1, carEntity.getName()); | ||
ps.setInt(2, carEntity.getPosition()); | ||
ps.setBoolean(3, carEntity.isWin()); | ||
ps.setLong(4, carEntity.getGameId()); | ||
} | ||
|
||
@Override | ||
public int getBatchSize() { | ||
return racingCars.size(); | ||
} | ||
}); | ||
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. 웨 않 simpleInsert? 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. 해 봐두 줗울지두 |
||
} | ||
|
||
@Override | ||
public List<CarEntity> findByRacingGameId(Long racingGameId) { | ||
return jdbcTemplate.query("SELECT * FROM car WHERE racing_game_id = " + racingGameId, | ||
(resultSet, rowNum) -> new CarEntity( | ||
resultSet.getString("name"), | ||
resultSet.getInt("position"), | ||
resultSet.getBoolean("is_win"), | ||
racingGameId | ||
)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package racingcar.dao; | ||
|
||
import java.util.List; | ||
import racingcar.dao.entity.RacingGameEntity; | ||
|
||
public interface RacingGameDao { | ||
|
||
Long save(RacingGameEntity racingGameEntity); | ||
|
||
List<RacingGameEntity> findAllByCreatedTimeAsc(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package racingcar.dao; | ||
|
||
import java.sql.PreparedStatement; | ||
import java.sql.Timestamp; | ||
import java.util.List; | ||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.jdbc.support.GeneratedKeyHolder; | ||
import org.springframework.jdbc.support.KeyHolder; | ||
import org.springframework.stereotype.Component; | ||
import racingcar.dao.entity.RacingGameEntity; | ||
|
||
@Component | ||
public class RacingGameJdbcDao implements RacingGameDao { | ||
|
||
private final JdbcTemplate jdbcTemplate; | ||
|
||
public RacingGameJdbcDao(JdbcTemplate jdbcTemplate) { | ||
this.jdbcTemplate = jdbcTemplate; | ||
} | ||
|
||
@Override | ||
public Long save(RacingGameEntity racingGameEntity) { | ||
String sql = "INSERT INTO racing_game (trial_count, created_at) VALUES (?,?)"; | ||
|
||
KeyHolder keyHolder = new GeneratedKeyHolder(); | ||
jdbcTemplate.update(con -> { | ||
PreparedStatement preparedStatement = con.prepareStatement(sql, new String[]{"id"}); | ||
preparedStatement.setInt(1, racingGameEntity.getTrialCount()); | ||
preparedStatement.setTimestamp(2, Timestamp.valueOf(racingGameEntity.getCreatedTime())); | ||
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. 이렇게 하는거구나 안 써봐서 처음 알았네 |
||
return preparedStatement; | ||
}, keyHolder); | ||
|
||
return keyHolder.getKey().longValue(); | ||
} | ||
|
||
@Override | ||
public List<RacingGameEntity> findAllByCreatedTimeAsc() { | ||
return jdbcTemplate.query( | ||
"SELECT * FROM racing_game ORDER BY created_at DESC ", | ||
(resultSet, rowNum) -> new RacingGameEntity( | ||
resultSet.getLong("id"), | ||
resultSet.getInt("trial_count"), | ||
resultSet.getTimestamp("created_at").toLocalDateTime() | ||
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. 이거 좋은데요 |
||
)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package racingcar.dao.entity; | ||
|
||
public class CarEntity { | ||
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.
|
||
|
||
private final String name; | ||
private final int position; | ||
private final boolean isWin; | ||
private final Long gameId; | ||
|
||
public CarEntity(String name, int position, boolean isWin, Long gameId) { | ||
this.name = name; | ||
this.position = position; | ||
this.isWin = isWin; | ||
this.gameId = gameId; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public int getPosition() { | ||
return position; | ||
} | ||
|
||
public boolean isWin() { | ||
return isWin; | ||
} | ||
|
||
public Long getGameId() { | ||
return gameId; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package racingcar.dao.entity; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
public class RacingGameEntity { | ||
|
||
private final Long id; | ||
private final int trialCount; | ||
private final LocalDateTime createdTime; | ||
|
||
public RacingGameEntity(Long id, int trialCount, LocalDateTime createdTime) { | ||
this.id = id; | ||
this.trialCount = trialCount; | ||
this.createdTime = createdTime; | ||
} | ||
|
||
public RacingGameEntity(int trialCount) { | ||
this(null, trialCount, LocalDateTime.now()); | ||
} | ||
|
||
public int getTrialCount() { | ||
return trialCount; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public LocalDateTime getCreatedTime() { | ||
return createdTime; | ||
} | ||
} |
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.
웨 static class?