ありがとうございます。
ここから 第15段階:教材ライブラリ強化(検索・分類・再利用・管理機能)設計 に進みます。
ここまでの設計では、教材は
| Content
└ ContentVersion
├ VideoContent
├ TextContent
├ QuizContent
└ FileContent
|
として管理しています。
しかし、実際の教材運用では教師が増えると以下の問題が発生します。
-
似た教材が大量に作成される
-
目的の教材を探せない
-
コース横断で教材を再利用したい
-
分野別・難易度別に整理したい
-
管理者が教材品質を確認したい
そのため、今回は 教材ライブラリ機能 を拡張します。
第15段階 全体構成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | Content
|
+------------+------------+
Tag Category
| |
Java / Spring プログラミング
|
ContentTag
|
LessonContent
|
Course利用
|
1. 教材ライブラリの役割
教材ライブラリは、
「教材そのものを管理する場所」
です。
コースとは分離します。
正しい関係
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | 教材ライブラリ
Javaとは
変数とは
Springとは
↓ 利用
コースA
Java基礎
↓ 利用
コースB
新人研修
|
NG設計
| Course
└ Lesson
└ Content
|
だけにすると、
教材コピーが発生します。
2. 教材カテゴリ管理
カテゴリを追加します。
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | プログラミング
├ Java
├ Spring
└ Python
ビジネス
├ DX
└ マネジメント
|
3. Categoryテーブル
階層構造にします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | CREATE TABLE content_categories (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
parent_id BIGINT,
name VARCHAR(100) NOT NULL,
sort_order INT,
created_at DATETIME,
updated_at DATETIME
);
|
4. Category Entity
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
26
27
28
29
30
31 | @Entity
@Table(name="content_categories")
@Getter
@Setter
public class ContentCategory {
@Id
@GeneratedValue(
strategy=GenerationType.IDENTITY
)
private Long id;
private String name;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="parent_id")
private ContentCategory parent;
private Integer sortOrder;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
|
5. Contentとの関連
教材は1カテゴリを基本にします。
理由:
検索しやすく、管理しやすいためです。
追加:
| @ManyToOne(fetch=FetchType.LAZY)
private ContentCategory category;
|
6. タグ管理
カテゴリ:
タグ:
として分離します。
例:
教材:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | Java入門
カテゴリ
Java
タグ
初心者
新人研修
プログラミング
|
7. Tagテーブル
| CREATE TABLE tags (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) UNIQUE,
created_at DATETIME
);
|
8. ContentTag中間テーブル
1
2
3
4
5
6
7
8
9
10
11
12 | CREATE TABLE content_tags (
content_id BIGINT,
tag_id BIGINT,
PRIMARY KEY(
content_id,
tag_id
)
);
|
9. Tag Entity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | @Entity
@Table(name="tags")
@Getter
@Setter
public class Tag {
@Id
@GeneratedValue(
strategy=GenerationType.IDENTITY
)
private Long id;
private String name;
}
|
10. 教材検索機能
検索条件:
1
2
3
4
5
6
7
8
9
10
11
12
13 | キーワード
教材種類
カテゴリ
タグ
作成者
状態
公開日時
|
11. SearchCondition拡張
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
26
27
28
29
30
31
32
33
34 | @Data
public class ContentSearchCondition {
private String keyword;
private String contentType;
private String status;
private Long categoryId;
private List<Long> tagIds;
private Long authorId;
private LocalDate fromDate;
private LocalDate toDate;
private Integer page=0;
private Integer size=20;
}
|
12. MyBatis検索SQL
例:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 | <select id="search">
SELECT
c.id,
cv.title,
cv.summary,
cat.name category_name,
u.username author_name
FROM contents c
JOIN content_versions cv
ON c.current_version_id=cv.id
LEFT JOIN content_categories cat
ON c.category_id=cat.id
JOIN users u
ON c.author_id=u.id
<where>
<if test="keyword != null">
AND (
cv.title LIKE CONCAT('%',#{keyword},'%')
OR
cv.summary LIKE CONCAT('%',#{keyword},'%')
)
</if>
<if test="categoryId != null">
AND c.category_id=#{categoryId}
</if>
<if test="status != null">
AND cv.status=#{status}
</if>
</where>
ORDER BY
cv.updated_at DESC
LIMIT #{size}
OFFSET #{offset}
</select>
|
13. 教材利用数表示
教師画面:
| 教材一覧
--------------------------------
Javaとは
利用数:5コース
--------------------------------
|
SQL:
| SELECT
COUNT(*)
FROM lesson_contents
WHERE content_id=?
|
14. 教材詳細画面改善
表示:
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
26
27
28
29
30
31
32
33
34
35
36
37 | Javaとは
--------------------------------
カテゴリ
Java
タグ
初心者
新人研修
利用コース
・Java基礎
・新人研修
作成者
山田先生
Version
3
状態
公開中
--------------------------------
|
15. 教材お気に入り
将来的に便利な機能です。
対象:
Favoriteテーブル
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | CREATE TABLE content_favorites (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT,
content_id BIGINT,
created_at DATETIME,
UNIQUE(
user_id,
content_id
)
);
|
16. 教材評価
教材品質改善用です。
例:
Reviewテーブル
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | CREATE TABLE content_reviews (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT,
content_id BIGINT,
rating INT,
comment TEXT,
created_at DATETIME
);
|
17. 教材ダッシュボード
管理者向け:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | 教材数
----------------
総教材
520
公開中
430
審査中
20
利用回数
1200
|
18. DashboardMapper
集計系はMyBatisです。
| @Mapper
public interface DashboardMapper {
DashboardSummaryDto summary();
}
|
DTO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | @Data
public class DashboardSummaryDto {
private Integer totalContents;
private Integer publishedContents;
private Integer reviewContents;
private Integer totalEnrollments;
}
|
19. 教材再利用機能
重要です。
教師が教材を探して、
を押します。
処理:
| Content
↓
LessonContent
登録
|
Service:
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
26
27
28
29
30
31 | @Transactional
public void reuseContent(
Long lessonId,
Long contentId){
LessonContent relation =
new LessonContent();
relation.setLesson(
lessonRepository
.getReferenceById(
lessonId
)
);
relation.setContent(
contentRepository
.getReferenceById(
contentId
)
);
repository.save(
relation
);
}
|
20. 教材ライブラリ画面
URL:
画面:
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
26
27
28
29
30
31
32
33
34
35
36 | ----------------------------------
教材検索
[Java ]
カテゴリ
[プログラミング]
種類
[動画]
検索
----------------------------------
Javaとは
動画
公開中
利用数
5
[利用する]
----------------------------------
|
21. 現在の完成構造
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | Content
|
+---------+---------+
Category Tag
|
LessonContent
|
Lesson
|
Course
|
第15段階終了時点
追加された機能:
✅ 教材ライブラリ
✅ カテゴリ階層管理
✅ タグ管理
✅ 高度検索
✅ 教材再利用
✅ 利用状況確認
✅ お気に入り設計
✅ 教材評価設計
✅ 管理ダッシュボード準備
次の 第16段階 では、管理者機能を強化します。
内容:
-
管理者ダッシュボード
-
ユーザー管理
-
ロール管理
-
教師管理
-
教材承認一覧改善
-
監査ログ検索
-
システム設定管理
-
Spring Security + 権限詳細設計
へ進みます。