コンテンツにスキップ

ありがとうございます。

ここから 第19段階:Spring Boot実装設計(Entity・Repository・Mapper・DTO・Form・Service・Controller構成) に進みます。

ここからは設計書レベルから、実際にJavaコードへ落とし込める構成に変換していきます。

今回はまず 全体アーキテクチャと主要クラス構成 を整理します。


第19段階の目的

採用する役割分担:

クラス 役割 技術
Entity DBテーブル1件を表現 JPA
Repository Entity CRUD Spring Data JPA
Mapper 検索・集計・JOIN MyBatis
DTO 画面表示データ Java
Form 入力受付・Validation Spring MVC
SearchCondition 検索条件 Java
Service 業務処理 Spring
Controller 画面制御 Spring MVC

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
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
com.example.lms

├ LmsApplication.java
│
├ config
│  ├ JpaConfig
│  ├ MyBatisConfig
│  ├ SecurityConfig
│  └ StorageConfig
│
├ security
│  ├ CustomUserDetails
│  ├ CustomUserDetailsService
│  └ LoginUser
│
├ common
│  ├ exception
│  ├ audit
│  ├ message
│  └ util
│
├ domain
│
│  ├ user
│  │  ├ entity
│  │  ├ repository
│  │  └ enum
│  │
│  ├ content
│  │  ├ entity
│  │  ├ repository
│  │  └ enum
│  │
│  ├ course
│  │  ├ entity
│  │  └ repository
│  │
│  ├ learning
│  │  ├ entity
│  │  └ repository
│  │
│  └ storage
│
├ application
│
│  ├ content
│  │  ├ ContentCreateService
│  │  ├ ContentEditService
│  │  └ ContentPublishService
│  │
│  ├ learning
│  │  └ LearningService
│  │
│  └ user
│      └ UserManagementService
│
├ infrastructure
│
│  ├ mapper
│  │
│  ├ storage
│  │
│  └ query
│
├ web
│
│  ├ admin
│  ├ teacher
│  ├ student
│  │
│  ├ dto
│  └ form
│
└ batch

2. Entity一覧

User系

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
User

Role

Permission

UserRole

RolePermission

SecurityLog

教材系

 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
Content

ContentVersion

VideoContent

TextContent

QuizContent

QuizChoice

FileContent

Attachment

ContentAttachment

ContentCategory

Tag

ContentTag

ApprovalHistory

コース系

1
2
3
4
5
6
7
Course

Section

Lesson

LessonContent

学習系

1
2
3
4
5
6
7
8
9
Enrollment

LearningProgress

VideoWatchHistory

QuizAnswerHistory

Certificate

3. Entity設計ルール

基底Entity

すべてのテーブルで共通項目を持たせます。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@MappedSuperclass
@Getter
@Setter
public abstract class BaseEntity {


    @CreatedDate
    private LocalDateTime createdAt;


    @LastModifiedDate
    private LocalDateTime updatedAt;

}

継承:

1
2
3
4
5
6
@Entity
public class Content
extends BaseEntity {


}

4. Content 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
32
33
34
@Entity
@Table(name="contents")
@Getter
@Setter
public class Content extends BaseEntity {


@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
private Long id;


@ManyToOne(fetch=FetchType.LAZY)
private User author;


@ManyToOne(fetch=FetchType.LAZY)
private ContentCategory category;


@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(
name="current_version_id"
)
private ContentVersion currentVersion;


@Enumerated(EnumType.STRING)
private ContentType contentType;


}

5. ContentVersion 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
32
33
34
35
36
37
38
39
40
41
42
43
@Entity
@Table(name="content_versions")
@Getter
@Setter
public class ContentVersion
extends BaseEntity {


@Id
@GeneratedValue(
strategy=GenerationType.IDENTITY
)
private Long id;


@ManyToOne(fetch=FetchType.LAZY)
private Content content;


private Integer versionNo;


private String title;


@Column(columnDefinition="TEXT")
private String summary;


@Enumerated(EnumType.STRING)
private ContentStatus status;


private LocalDateTime submittedAt;


private LocalDateTime approvedAt;


private LocalDateTime publishedAt;


}

6. Repository構成

基本CRUDはJPA。

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
repository

├ ContentRepository

├ ContentVersionRepository

├ UserRepository

├ CourseRepository

└ LessonRepository

ContentRepository

1
2
3
4
5
6
@Repository
public interface ContentRepository
extends JpaRepository<Content,Long>{


}

7. MyBatis Mapper構成

検索・集計用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
mapper

├ ContentMapper

├ ApprovalMapper

├ DashboardMapper

├ LearningMapper

└ UserMapper

8. ContentMapper

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@Mapper
public interface ContentMapper {


List<ContentListDto> search(
    ContentSearchCondition condition
);


ContentDetailDto findDetail(
    Long id
);


}

9. DTO構成

画面単位で作ります。

理由:

Entityをそのまま画面へ渡さない。


構成:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dto

├ content

│ ├ ContentListDto

│ ├ ContentDetailDto

│ └ ContentLibraryDto


├ learning

│ ├ CourseProgressDto

│ └ LessonDto


└ admin

  ├ DashboardDto

  └ UserListDto

10. Form構成

入力専用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
form

├ content

│ ├ ContentCreateForm

│ ├ TextContentForm

│ ├ VideoContentForm

│ ├ QuizContentForm


├ user

│ └ UserEditForm


└ learning

    └ QuizAnswerForm

11. Service構成

業務処理単位。


教材

1
2
3
4
5
6
7
ContentCreateService

役割:

・教材登録
・Version作成
・詳細登録

1
2
3
4
5
6
ContentEditService

役割:

・Versionコピー
・編集開始

1
2
3
4
5
6
ContentPublishService

役割:

・承認
・公開

12. Controller構成

URL単位。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
controller

├ admin

│ ├ AdminDashboardController

│ ├ UserAdminController

│ └ ApprovalController


├ teacher

│ ├ TeacherContentController

│ └ ContentLibraryController


└ student

  ├ StudentCourseController

  └ LearningController

13. 教師教材Controller例

 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
@Controller
@RequestMapping("/teacher/content")
@RequiredArgsConstructor
public class TeacherContentController {


private final ContentCreateService service;


@GetMapping("/create")
public String create(
Model model){


model.addAttribute(
"form",
new ContentCreateForm()
);


return
"teacher/content/create";

}


@PostMapping("/create")
public String save(
@Valid
@ModelAttribute ContentCreateForm form,
BindingResult result){


if(result.hasErrors()){

return
"teacher/content/create";

}


service.create(form);


return
"redirect:/teacher/content";

}


}

14. Service設計ルール

Controller:

1
画面制御のみ

Service:

1
2
業務判断
@Transactional

Repository / Mapper:

1
DB操作

15. 依存方向

重要です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
web

 ↓

application

 ↓

domain


application

 ↓

repository


application

 ↓

mapper

禁止:

1
2
3
4
5
Entity

↓

Controller

直接操作は禁止。


16. JPAとMyBatis利用基準

今回の設計:

JPA

利用:

  • 登録

  • 更新

  • 削除

  • Entity関連操作

例:

1
2
3
4
5
Content登録

User変更

受講登録

MyBatis

利用:

  • 一覧

  • 検索

  • 集計

  • JOIN

例:

1
2
3
4
5
6
7
教材一覧

管理者Dashboard

進捗率計算

承認一覧

17. トランザクション例

教材公開:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ContentPublishService

@Transactional

↓

旧Version

ARCHIVED


↓

新Version

PUBLISHED


↓

AuditLog

INSERT

18. 第19段階終了時点

設計完成:

✅ パッケージ構成
✅ Entity配置
✅ Repository配置
✅ MyBatis Mapper配置
✅ DTO設計
✅ Form設計
✅ Service設計
✅ Controller設計
✅ JPA/MyBatis役割分担
✅ 実装ルール


次の 第20段階 では、いよいよコード生成フェーズへ移ります。

予定:

第20段階:ユーザー認証・Spring Security実装

内容:

  1. User Entity完全版

  2. Role / Permission Entity

  3. UserDetailsService

  4. Login画面

  5. Spring Security Config

  6. 権限制御

  7. ログインユーザー取得

  8. 教師・管理者・受講者別アクセス制御

を実装コード形式で作成します。