-
Notifications
You must be signed in to change notification settings - Fork 297
3단계 - 수강신청(DB 적용) #769
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
base: heewonham
Are you sure you want to change the base?
3단계 - 수강신청(DB 적용) #769
Changes from 5 commits
845e2a8
fbca015
37e1180
623f840
c17e5ec
f8e00f3
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,30 @@ | ||
package nextstep.courses.domain; | ||
|
||
public class Student { | ||
Long id; | ||
public Student() { | ||
} | ||
public Student(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public boolean contains(Long studentId) { | ||
return id.equals(studentId); | ||
} | ||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
Student student = (Student) o; | ||
return id != null && id.equals(student.id); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return id != null ? id.hashCode() : 0; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package nextstep.courses.domain; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
public class Students { | ||
private Set<Student> students = new HashSet<>(); | ||
|
||
public void addStudent(Student student) { | ||
if (contains(student)) { | ||
throw new IllegalArgumentException("이미 등록된 학생입니다."); | ||
} | ||
students.add(student); | ||
} | ||
|
||
public void removeStudent(Student student) { | ||
students.remove(student); | ||
} | ||
|
||
public boolean contains(Student student) { | ||
return students.stream() | ||
.anyMatch(s -> s.equals(student)); | ||
} | ||
|
||
public int size() { | ||
return students.size(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
package nextstep.courses.domain; | ||
|
||
import java.util.Objects; | ||
|
||
public class TuitionFee { | ||
private final int amount; | ||
|
||
|
@@ -10,7 +12,20 @@ public TuitionFee(int amount) { | |
this.amount = amount; | ||
} | ||
|
||
public int getAmount() { | ||
return amount; | ||
public boolean isSameAmount(int amount) { | ||
return this.amount == amount; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (!(o instanceof TuitionFee)) return false; | ||
TuitionFee that = (TuitionFee) o; | ||
return amount == that.amount; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
Comment on lines
+23
to
+32
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 Objects.hash(amount); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package nextstep.courses.infrastructure; | ||
|
||
import nextstep.courses.domain.Image; | ||
import nextstep.courses.domain.Period; | ||
import nextstep.courses.domain.Session; | ||
import nextstep.courses.domain.SessionStatus; | ||
import nextstep.courses.domain.PaidSession; | ||
import nextstep.courses.domain.FreeSession; | ||
|
||
import org.springframework.jdbc.core.JdbcTemplate; | ||
import org.springframework.jdbc.core.RowMapper; | ||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@Repository | ||
public class JdbcSessionRepository { | ||
private final JdbcTemplate jdbcTemplate; | ||
|
||
public JdbcSessionRepository(JdbcTemplate jdbcTemplate) { | ||
this.jdbcTemplate = jdbcTemplate; | ||
} | ||
|
||
public void save(Session session, Long courseId) { | ||
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. Session이 courseId를 가지는 구조는 어떤가요? |
||
Long imageId = null; | ||
if (session.getCoverImage() != null) { | ||
imageId = insertImage(session.getCoverImage()); | ||
} | ||
|
||
String sql = "insert into session (name, type, start_date, end_date, status, capacity, tuition_fee, image_id, course_id) " + | ||
"values (?, ?, ?, ?, ?, ?, ?, ?, ?)"; | ||
|
||
jdbcTemplate.update(sql, | ||
session.getName(), | ||
session.getType().name(), | ||
session.getPeriod().getStartDate(), | ||
session.getPeriod().getEndDate(), | ||
session.getStatus().name(), | ||
session instanceof PaidSession ? ((PaidSession) session).getCapacity() : null, | ||
session instanceof PaidSession ? ((PaidSession) session).getTuitionFee() : null, | ||
imageId, | ||
courseId | ||
); | ||
|
||
} | ||
|
||
public List<Session> findAll() { | ||
String sql = "select s.*, i.file_name, i.content_type, i.size_in_bytes, i.width, i.height " + | ||
"from session s left join image i on s.image_id = i.id"; | ||
return jdbcTemplate.query(sql, sessionRowMapper()); | ||
} | ||
|
||
public Session findById(Long id) { | ||
String sql = "select s.*, i.file_name, i.content_type, i.size_in_bytes, i.width, i.height " + | ||
"from session s left join image i on s.image_id = i.id where s.id = ?"; | ||
return jdbcTemplate.queryForObject(sql, sessionRowMapper(), id); | ||
} | ||
|
||
public void update(Session session) { | ||
String sql = "update session set name = ?, start_date = ?, end_date = ?, status = ?, capacity = ?, tuition_fee = ? where id = ?"; | ||
jdbcTemplate.update(sql, | ||
session.getName(), | ||
session.getPeriod().getStartDate(), | ||
session.getPeriod().getEndDate(), | ||
session.getStatus().name(), | ||
session instanceof PaidSession ? ((PaidSession) session).getCapacity() : null, | ||
session instanceof PaidSession ? ((PaidSession) session).getTuitionFee() : null, | ||
session.getId() | ||
); | ||
} | ||
|
||
public void deleteById(Long id) { | ||
jdbcTemplate.update("delete from session where id = ?", id); | ||
} | ||
|
||
private Long insertImage(Image image) { | ||
SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate) | ||
.withTableName("image") | ||
.usingGeneratedKeyColumns("id"); | ||
|
||
Map<String, Object> params = new HashMap<>(); | ||
params.put("file_name", image.getFileName()); | ||
params.put("content_type", image.getContentType()); | ||
params.put("size_in_bytes", image.getSizeInBytes()); | ||
params.put("width", image.getWidth()); | ||
params.put("height", image.getHeight()); | ||
|
||
return insert.executeAndReturnKey(params).longValue(); | ||
} | ||
|
||
private RowMapper<Session> sessionRowMapper() { | ||
return (rs, rowNum) -> { | ||
SessionStatus status = SessionStatus.valueOf(rs.getString("status")); | ||
Period period = new Period(rs.getDate("start_date").toLocalDate(), rs.getDate("end_date").toLocalDate()); | ||
|
||
Image image = null; | ||
if (rs.getString("file_name") != null) { | ||
image = new Image( | ||
rs.getString("file_name"), | ||
rs.getString("content_type"), | ||
rs.getLong("size_in_bytes"), | ||
rs.getInt("width"), | ||
rs.getInt("height") | ||
); | ||
} | ||
|
||
String type = rs.getString("type"); | ||
if (type.equals("FREE")) { | ||
return new FreeSession(rs.getLong("id"), rs.getString("name"), period, image, status); | ||
} else { | ||
return new PaidSession(rs.getLong("id"), rs.getString("name"), period, image, status, | ||
rs.getInt("capacity"), rs.getInt("tuition_fee")); | ||
} | ||
}; | ||
} | ||
} |
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.
#728 (comment)
#728 (comment)
이 두 부분이 약간 상충되는 것 같아 질문드립니다.
어떤 부분은 get을 쓰고 어떤 부분은 이렇게 함수를 만드는데 구분할 수 있는 방법은 무엇일까요?
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.
그럼에도 불구하고 게터만으로 객체의 상태를 검증하기 어려운 경우,
테스트를 목적으로 하는 메서드를
public
대신protected
로 선언하는 방법도 있습니다.보통 테스트 클래스는 테스트 대상 클래스와 같은 패키지에 위치하므로,
protected
메서드에도 접근할 수 있어서요.이러면 테스트의 편의성을 확보하면서도, 외부에서의 불필요한 접근은 제한할 수 있게됩니다 😄
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.
@nooose 아하 이해했습니다. 도메인 객체 책임에 해당하는지를 생각해보면 되겠군요!!
상세한 설명 감사합니다 🙏