Skip to content
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

3단계 - 수강신청(DB 적용) #642

Open
wants to merge 9 commits into
base: lee-won-suk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
15 changes: 15 additions & 0 deletions STEP3README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 학습 관리 시스템(Learning Management System)

## step3 요구사항

1. [x] 앞단계에서 구현한 도메인 모델 DB와 매핑하고 데이터 저장
2.
2. 테이블 설계하고 객체매핑
2. [x] Payments는 테이블 매핑 미고려

## 관련 클래스

1. DB 테이블 resources/schema.sql
2. jdbcCourseRepository
3. CourseRepositoryTest

20 changes: 0 additions & 20 deletions src/main/java/nextstep/courses/Exception/ResponseType.java

This file was deleted.

10 changes: 5 additions & 5 deletions src/main/java/nextstep/courses/domain/Course.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ public class Course {
private Long creatorId;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private List<Session> sessionList;
private List<Session> sessions;
Copy link
Member

Choose a reason for hiding this comment

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

연관관계를 가지도록 매핑하셨네요
Course를 조회하는 시점에 같이 조회해야하지 않을까요?
따로 Session 리스트를 주입하는 부분을 찾을 수 없는 것 같아서요


public Course() {
}

public Course(String title, Long creatorId) {
this(0L, title, creatorId, LocalDateTime.now(), null);
this(0L, title, creatorId, LocalDateTime.now(), null,1);
}

public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt) {
public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt, int classNumber) {
this.id = id;
this.title = title;
this.creatorId = creatorId;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
sessionList = new ArrayList<>();
classNumber = count.incrementAndGet();
sessions = new ArrayList<>();
this.classNumber = classNumber;
}

public String getTitle() {
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/nextstep/courses/domain/PricingType.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package nextstep.courses.domain;

import nextstep.courses.Exception.CustomException;
import nextstep.courses.exception.CustomException;
import nextstep.payments.domain.Payment;

public class PricingType {

private final int sessionAmount;
private boolean isPremium;
private final boolean isPremium;
Copy link
Member

Choose a reason for hiding this comment

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

지금은 두개의 타입만 존재하지만,
미래를 생각해서 boolean 타입대신 enum 타입으로 유연하게 변경하면 어떨까요?

요구사항이 추가되어 다른 타입의 강의도 생성될 수 있지 않을까요?




public PricingType(boolean isPremium, int sessionAmount) {
validate(isPremium,sessionAmount);
Expand All @@ -32,4 +34,12 @@ public void validateAmount(Payment payment) {
throw CustomException.NOT_MATCHING_SESSION_AMOUNT;
}
}

public int getSessionAmount() {
return sessionAmount;
}

public boolean getIsPremium() {
return isPremium;
}
}
53 changes: 46 additions & 7 deletions src/main/java/nextstep/courses/domain/Session.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
package nextstep.courses.domain;

import nextstep.courses.Exception.CustomException;
import nextstep.courses.domain.sessionimage.SessionImage;
import nextstep.courses.exception.CustomException;
import nextstep.courses.domain.image.SessionImage;
import nextstep.payments.domain.Payment;
import nextstep.users.domain.NsUser;

import java.util.ArrayList;
import java.util.List;

public class Session {
private List<NsUser> students;
private Long id;
private List<Long> students;
private PricingType pricingType;
private SessionState state;
private SessionImage image;
private int maxStudentCount;
private SessionDate date;


public Session(PricingType pricingType, int maxStudentCount, SessionState state, SessionDate date
, SessionImage image) {
this(0L, new ArrayList<Long>(),pricingType,state,image,maxStudentCount,date);
}

public Session(List<Long> students, PricingType pricingType, SessionState state, SessionImage image, int maxStudentCount, SessionDate date) {
this.id = 0L;
this.students = students;
this.pricingType = pricingType;
this.students = new ArrayList<>();
this.maxStudentCount = maxStudentCount;
this.state = state;
this.date = date;
this.image = image;
this.maxStudentCount = maxStudentCount;
this.date = date;
}

public Session(Long id, List<Long> students, PricingType pricingType, SessionState state, SessionImage image, int maxStudentCount, SessionDate date) {
this.id = id;
this.students = students;
this.pricingType = pricingType;
this.state = state;
this.image = image;
this.maxStudentCount = maxStudentCount;
this.date = date;
}

public void requestSession(Payment payment) {
Expand All @@ -47,4 +62,28 @@ private void validateSessionState() {

}

public List<Long> getStudents() {
return students;
}

public PricingType getPricingType() {
return pricingType;
}

public SessionState getState() {
return state;
}

public SessionImage getImage() {
return image;
}

public int getMaxStudentCount() {
return maxStudentCount;
}

public SessionDate getDate() {
return date;
}

}
10 changes: 9 additions & 1 deletion src/main/java/nextstep/courses/domain/SessionDate.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package nextstep.courses.domain;

import nextstep.courses.Exception.CustomException;
import nextstep.courses.exception.CustomException;

import java.time.LocalDateTime;

Expand All @@ -15,4 +15,12 @@ public SessionDate(LocalDateTime startDate, LocalDateTime endDate) {
this.startDate = startDate;
this.endDate = endDate;
}

public LocalDateTime getStartDate() {
return startDate;
}

public LocalDateTime getEndDate() {
return endDate;
}
}
6 changes: 6 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package nextstep.courses.domain;

public interface SessionRepository {
long save(Session session);
Session findById(Long id);
}
3 changes: 3 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionState.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
public enum SessionState {
READY("READY"), START("START"), END("END");
Copy link
Member

Choose a reason for hiding this comment

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

enum 이름과 상태를 동일하게 적어주셨는데
어떤 이유인지도 설명 부탁드립니다!


public String getState() {
return state;
}

public String state;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package nextstep.courses.domain.sessionimage;
package nextstep.courses.domain.image;

import nextstep.courses.Exception.CustomException;
import nextstep.courses.exception.CustomException;

public class ImageCapacity {

Expand All @@ -9,6 +9,7 @@ public class ImageCapacity {

private final int imageSize;


public ImageCapacity(int imageSize) {
validateSize(imageSize);
this.imageSize = imageSize;
Expand All @@ -19,4 +20,9 @@ private void validateSize(int imageSize) {
throw CustomException.OVER_MAX_IMAGE_CAPACITY;
}
}

public int getImageSize() {
return imageSize;
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package nextstep.courses.domain.sessionimage;
package nextstep.courses.domain.image;

import nextstep.courses.Exception.CustomException;
import nextstep.courses.exception.CustomException;

import java.math.BigDecimal;
import java.math.RoundingMode;
Expand Down Expand Up @@ -29,4 +29,13 @@ private void validateSize(int width, int height) {
throw CustomException.IMAGE_PERCENT_ERROR;
}
}


public int getWidth() {
return width;
}

public int getHeight() {
return height;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package nextstep.courses.domain.sessionimage;
package nextstep.courses.domain.image;

import nextstep.courses.Exception.CustomException;
import nextstep.courses.exception.CustomException;

import java.util.Arrays;

Expand All @@ -12,7 +12,6 @@ public enum ImageType {
png,
svg;


public static ImageType validateType(String imageType) {
return Arrays.stream(values()).filter(type -> type.name().equals(imageType))
.findFirst()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
package nextstep.courses.domain.sessionimage;
package nextstep.courses.domain.image;

public class SessionImage {

private final ImageCapacity capacity;
private final ImageType type;
private final ImageSize size;


public SessionImage(ImageCapacity capacity, ImageType type, ImageSize size) {
ImageType.validateType(type.name());
this.capacity = capacity;
this.type = type;
this.size = size;
}

public ImageCapacity getCapacity() {
return capacity;
}

public ImageType getType() {
return type;
}

public ImageSize getSize() {
return size;
}

}
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
package nextstep.courses.Exception;
package nextstep.courses.exception;

public class CustomException extends RuntimeException {

public static final CustomException NOT_ALLOWED_DATE = new CustomException(ResponseType.NOT_ALLOWED_DATE_MESSAGE);
public static final CustomException OVER_MAX_IMAGE_CAPACITY = new CustomException(ResponseType.OVER_MAX_IMAGE_CAPACITY);
public static final CustomException IMAGE_SIZE_ERROR = new CustomException(ResponseType.IMAGE_SIZE_ERROR);
public static final CustomException IMAGE_PERCENT_ERROR = new CustomException(ResponseType.IMAGE_PERCENT_ERROR);
public static final CustomException NOT_ALLOWED_PREMIUM_AMOUNT = new CustomException(ResponseType.NOT_ALLOWED_PREMIUM_AMOUNT);
public static final CustomException NOT_ALLOWED_FREE_AMOUNT = new CustomException(ResponseType.NOT_ALLOWED_FREE_AMOUNT);
public static final CustomException NOT_MATCHING_SESSION_AMOUNT = new CustomException(ResponseType.NOT_MACHING_SESSION_AMOUNT);
public static final CustomException MAX_STUDENTS_OVER = new CustomException(ResponseType.MAX_STUDENTS_OVER);
public static final CustomException INVALID_SESSION_STATE = new CustomException(ResponseType.INVALID_SESSION_STATE);
public static final CustomException INVALID_IMAGE_TYPE = new CustomException(ResponseType.INVALID_IMAGE_TYPE);
public static final CustomException NOT_ALLOWED_DATE = new CustomException("허용되지 않은 시작날짜입니다.");
public static final CustomException OVER_MAX_IMAGE_CAPACITY = new CustomException("이미지 사이즈는 1MB 이하여야 합니다.");
public static final CustomException IMAGE_SIZE_ERROR = new CustomException("이미지 사이즈 오류입니다.");
public static final CustomException IMAGE_PERCENT_ERROR = new CustomException("이미지 비율 오류");
public static final CustomException NOT_ALLOWED_PREMIUM_AMOUNT = new CustomException("유료강의 금액은 0원이 될 수 없습니다.");
public static final CustomException NOT_ALLOWED_FREE_AMOUNT = new CustomException("무료 강의 금액이 0원이 아닙니다.");
public static final CustomException NOT_MATCHING_SESSION_AMOUNT = new CustomException("강의 금액과 맞지 않습니다.");
public static final CustomException MAX_STUDENTS_OVER = new CustomException("수강인원 초과");
public static final CustomException INVALID_SESSION_STATE = new CustomException("강의신청 기간이 아닙니다.");
public static final CustomException INVALID_IMAGE_TYPE = new CustomException("이미지 타입이 올바르지 않습니다.");

public CustomException(ResponseType responseType) {
super(responseType.message);
public CustomException(String message) {
super(message);
}

@Override
public synchronized Throwable fillInStackTrace() {
return this;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ public JdbcCourseRepository(JdbcOperations jdbcTemplate) {

@Override
public int save(Course course) {
String sql = "insert into course (title, creator_id, created_at) values(?, ?, ?)";
return jdbcTemplate.update(sql, course.getTitle(), course.getCreatorId(), course.getCreatedAt());
String sql = "insert into course (title, creator_id, created_at, class_number) values(?, ?, ?,?)";
return jdbcTemplate.update(sql, course.getTitle(), course.getCreatorId(), course.getCreatedAt(),1);
Copy link
Member

Choose a reason for hiding this comment

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

순서를 지키면서 바인딩 시키는 것은 실수할 우려도 있고, 어려울 수 있어요
NamedParameterJdbcTemplate 을 참고하면 좋겠습니다.
참고만 해주세요!

Copy link
Author

Choose a reason for hiding this comment

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

훨씬 편하네요.. SqlParameterSource라는 것도 있어서 이걸로 매핑해보니 훨씬 가독성도 좋았습니다. 감사합니다.

}

@Override
public Course findById(Long id) {
String sql = "select id, title, creator_id, created_at, updated_at from course where id = ?";
String sql = "select id, title, creator_id, created_at, updated_at, class_number from course where id = ?";
RowMapper<Course> rowMapper = (rs, rowNum) -> new Course(
Copy link
Member

Choose a reason for hiding this comment

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

매조회마다 매퍼를 생성할 필요는 없어보여요 상수로 두고 재사용할 수 있게 만들어보면 좋겠습니다.

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다. rowMapper는 각행을 어떻게 매핑할 것인지 정의하는 것이기 때문에 말씀하신 방법대로 하는게 매 생성시 new로 할당받는 것을 줄일 수 있을 것 같습니다. 수정했습니다.

rs.getLong(1),
rs.getString(2),
rs.getLong(3),
toLocalDateTime(rs.getTimestamp(4)),
toLocalDateTime(rs.getTimestamp(5)));
toLocalDateTime(rs.getTimestamp(5)),
rs.getInt(6)
);
Copy link
Member

Choose a reason for hiding this comment

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

컬럼 순서대신 이름으로 매핑시켜보면 어떨까요?
순서는 실수를 유발할 수 있고, 쿼리 변경 시 많은 변경이 요구됩니다.

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다. 이름으로 매핑하는 방식을 처음알았네요
이름으로 넣어보니 훨씬 가독성이 있었습니다.

return jdbcTemplate.queryForObject(sql, rowMapper, id);
}

Expand Down
Loading