教材管理システムを構築します。 ユースケースとして、管理者、教師、メンター、受講者がいます。 教師は、コンテンツを提供する人です。作成者には教師の名前が入ります。 教師は、自身のアカウントでコンテンツを作成し、できたら保存か申請ができます。申請を出すと管理者承認し、公開となります。 公開されたコンテンツは受講者が受講できます。 メンターは、受講者の質問対応や学習計画のフォローをする人です。今回のシステム内には機能としては登場しないかもしれませんが、将来的に追加する可能性があります。
教材構成
コース > セクション > サブセクション > サブサブセクション > ... > レッスン
コースにセクションがあります。 セクションにレッスンを紐づけます。 セクションは親子構造にして、階層を設計上は無限にできるようにします。
レッスンにはコンテンツを1つ以上紐づけます。 コンテンツには、名称、概要、コンテンツタイプ、作成者、ステータス(下書き、審査中、公開待ち、公開中)、公開日時などは共通で管理します。コンテンツタイプは、ビデオ、テキスト、クイズ(選択式問題)、ファイルなどの分類をします。 ビデオコンテンツは、youtubeやVimeoのリンクを指定する方法と、Cloudflare R2で独自に構築する方法で、ブラウザ内でのストリーミング配信にしたいです。名称、概要、ビデオ種別、ビデオID、ビデオURLは含めてください。
テキストコンテンツは、名称、概要、本文を含めてください。本文をプレーンテキストか、マークダウン形式で入力し、表示の際にはデザインされたHTML形式で表示されるようにしたいです。
クイズコンテンツは、クイズカテゴリ、名称、問題文と選択肢があり、複数の選択肢から正解を選び正解を判定するようにしたいです。基本的には4択式で1つが正解を考えいますが、6択から正解を2つを選ぶような問題も作れるように汎用的な構造にしたいです。
ファイルコンテンツは、名称、概要、ファイル種別を含めてください。PDF、zip、txt、オフィス形式のファイルなどをタイトルと説明付きで登録し、ダウンロードが可能なようにしたいです。
役割と使用技術
Java、Spring、JPA、MyBatis、MySQL、SpringSecurity、Thymeleafを効率的に利用したいです。 以下をベースに設計してください。
| クラス | 役割 | 使用技術 |
|---|---|---|
| Entity | テーブル1件を表す。登録・更新・削除を担当 | JPA |
| Repository | Entityに対するCRUDを担当 | Spring Data JPA |
| Mapper | JOIN・集計・検索などのSQLを担当 | MyBatis |
| DTO | 画面表示やAPIレスポンス用のデータ | 共通 |
| Form | 入力値の受け取りとバリデーション | Spring MVC |
| SearchCondition | 検索条件の受け渡し | MyBatis |
| Service | ビジネスロジックを実装し、JPAとMyBatisを組み合わせる | Spring |
まずは、1段階をお願いします。
とても良い設計方針だと思います。
この規模になると、最初からテーブルを作り始めるよりも、DDD(ドメイン駆動設計)まではいかなくても、「ドメイン設計 → DB設計 → Entity → Service」 の順番で設計すると後々の保守性が大きく変わります。
私であれば、このシステムは以下のように 5段階 に分けて設計します。
| 段階 | 内容 |
|---|---|
| 第1段階 | ドメイン設計(機能・責務・画面・ERの土台) |
| 第2段階 | DB設計(DDL・ER図・インデックス) |
| 第3段階 | Springプロジェクト構成(Entity・Repository・Mapper・DTO・Formなど) |
| 第4段階 | 教材作成・承認・公開フロー |
| 第5段階 | 受講機能・学習履歴・進捗・クイズ・メンター機能 |
第1段階 ドメイン設計
まずは「何を管理するシステムか」を整理します。
システム全体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
ドメイン一覧
まずは管理する情報を決めます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
このくらいに分けるとかなり整理しやすくなります。
教材構造
ご要望どおり
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Sectionを親子構造にします。
1 2 3 4 5 6 7 | |
これだけで
1 2 3 4 5 6 7 8 9 10 11 | |
のような無限階層になります。
Lesson
Lessonは教材のまとまりです。
1 2 3 4 5 6 7 8 9 10 11 | |
つまり
1 2 3 4 5 6 7 8 9 10 11 12 | |
という構造になります。
Content
ここが重要です。
共通情報だけを持たせます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
動画でも
テキストでも
PDFでも
全部ここを通ります。
コンテンツ種別
1 2 3 4 5 6 7 | |
Enum管理がおすすめです。
Video
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
video_type
1 2 3 4 5 | |
R2の場合
1 2 3 4 5 | |
などを追加してもいいです。
Text
1 2 3 4 5 6 7 | |
表示時
1 2 3 4 5 6 7 8 9 | |
になります。
Quiz
Quizは少し汎用的に作ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
例えば
1 2 3 | |
なら
1 2 3 | |
6択で
正解2つ
なら
1 2 3 | |
になります。
Choice
1 2 3 4 5 6 7 8 9 10 11 | |
何択でも対応できます。
1 2 3 4 5 6 7 8 9 10 11 | |
全部Choiceになります。
File
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
file_type
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
承認フロー
教師
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
状態は
1 2 3 4 5 6 7 8 9 | |
くらいがおすすめです。
学習履歴
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
別テーブル
1 | |
で管理します。
Spring構成
ご提示いただいた構成は非常に良く、このシステムにも適しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
JPA と MyBatis の役割分担
今回の規模では、以下のように役割を明確に分けると保守しやすくなります。
| クラス | 役割 | 技術 |
|---|---|---|
| Entity | 1テーブル1レコードを表現し、永続化対象とする | JPA |
| Repository | 単一テーブルのCRUD(登録・更新・削除・主キー検索) | Spring Data JPA |
| Mapper | JOIN・集計・検索・一覧表示・ツリー取得などのSQL | MyBatis |
| DTO | 画面表示・API・一覧・詳細など用途別データ | 共通 |
| Form | 画面入力とバリデーション | Spring MVC |
| SearchCondition | 検索条件の受け渡し(キーワード・ステータス・作成者など) | MyBatis |
| Service | トランザクション制御と業務ロジック。RepositoryとMapperを組み合わせる | Spring |
この役割分担にすると、更新処理はJPAに集約され、一方で教材ツリーや一覧検索のような複雑なSQLはMyBatisに任せられるため、それぞれの長所を活かせます。
第2段階で設計する内容
次の段階では、このドメイン設計を具体的なデータモデルへ落とし込みます。
-
全テーブル一覧(約20~30テーブルを想定)
-
ER図
-
MySQL DDL
-
JPA Entity設計
-
外部キー・インデックス設計
-
Enum設計(ロール、ステータス、コンテンツ種別など)
-
監査項目(作成者・更新者・作成日時・更新日時)の共通化
-
承認フローや学習履歴を考慮した正規化
この順番で進めることで、その後のSpring Boot実装まで一貫性のある設計にできます。