SSA/Back
[SSA] 강의 도메인
하가네
2025. 5. 4. 19:51
강의와 관련한 기능이 핵심인 서비스인 만큼 강의 도메인을 보여 드리겠습니다 ..
우선 강사와 학생이 메인이지만 학부모가 강사에게 면담을 신청할 수도 있도록 구성해 봤습니다.
그런데 강의와 면담 간에 동일한 필드가 존재함을 인지하고 정규화를 시도했습니다.
@SQLRestriction("deleted_at is null")
@SQLDelete(sql = "UPDATE schedule SET deleted_at = CURRENT_TIMESTAMP WHERE id = ?")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
@Table(name = "schedule")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Schedule extends SoftDeletedEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "schedule_id")
private Long id;
@Column(name = "title", nullable = false)
private String title;
@Column(name = "start_time", nullable = false)
private LocalDateTime startTime;
@Column(name = "end_time", nullable = false)
private LocalDateTime endTime;
@Column(name = "memo")
private String memo;
public Schedule(String title, LocalDateTime startTime, LocalDateTime endTime, String memo) {
this.title = title;
this.startTime = startTime;
this.endTime = endTime;
this.memo = memo;
}
protected void updateSchedule(Schedule schedule) {
this.title = schedule.title;
this.startTime = schedule.startTime;
this.endTime = schedule.endTime;
this.memo = schedule.memo;
}
}
기본적으로 강의와 면담 모두 가질 수 있는 필드들로 묶어서 Schedule 이라는 클래스로 관리합니다.
그리고 Schedule을 상속받은 Lecture와 Consultation이 존재하는데
각각 다음과 같습니다.
@DiscriminatorValue("LECTURE")
@Table(name = "lecture")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Lecture extends Schedule {
@ManyToOne
@JoinColumn(name = "tutor_id")
private Tutor tutor;
@Column(nullable = false)
private int capacity;
@Column(nullable = false)
private int enrolledCount = 0;
@OneToMany(mappedBy = "lecture", cascade = CascadeType.ALL, orphanRemoval = true)
private List<LectureEnrollment> lectureEnrollments;
public Lecture(
String title,
LocalDateTime startTime,
LocalDateTime endTime,
String memo,
Tutor tutor,
int capacity
) {
super(title, startTime, endTime, memo);
this.tutor = tutor;
this.capacity = capacity;
}
}
@DiscriminatorValue("CONSULTATION")
@Table(name = "consultation")
@NoArgsConstructor
@Getter
@Entity
public class Consultation extends Schedule {
@ManyToOne
@JoinColumn(name = "tutor_id")
private Tutor tutor;
@OneToMany(mappedBy = "consultation", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ConsultationAttendee> consultationAttendees;
public Consultation(
String title,
LocalDateTime startTime,
LocalDateTime endTime,
String memo,
Tutor tutor
) {
super(title, startTime, endTime, memo);
validatePastTime(startTime, endTime);
this.tutor = tutor;
}
}
구체적인 도메인 로직은 너무 길어서 생략하였습니다.
그리고 Schedule의 타입으로 어떤 것인지 enum으로 필드를 관리할 수도 있었는데,
그냥 @DiscriminatorValue() 어노테이션으로 어떤 타입인지 관리할 수 있도록 구성해 봤습니다.