A-1 (#86) / A-2 (#272) で整えた 4 層パッケージ上で、GET /api/tasks/{id} 実装の基盤層(shared 例外基底 + JPA Entity / Domain POJO 分離 + Repository ポート)を整備する。
N4 (#86) を 7 分割した B-1 スコープ(2026-05-30 Cowork 3 再分割、B が ~18 ファイル / テスト 5 種類で実装 Claude の単一 PR キャパシティ超過の risk あり):
やること
1. shared/exception/ 配下を新規作成
| ファイル |
内容 |
shared/exception/DomainException.java |
abstract class DomainException extends RuntimeException、@ResponseStatus 禁止、業務例外基底 |
shared/exception/package-info.java |
@NullMarked |
2. task/domain/Task.java(Domain POJO)を新規作成
task/adapter/persistence/Task.java(現 JPA Entity)から JPA アノテーション剥離した POJO を task/domain/ に新規:
- Field:
Long id / Long tenantId / String title / String description / Priority priority / TaskStatus status / Visibility visibility / Long assigneeId / LocalDate dueDate / LocalDateTime createdAt / LocalDateTime updatedAt
@Entity / @Column / @Id 等 JPA 依存禁止、Spring 非依存
- lombok
@Getter + all-args constructor、equals/hashCode は id ベース
3. task/adapter/persistence/Task.java を TaskJpaEntity.java に rename
git mv task/adapter/persistence/Task.java task/adapter/persistence/TaskJpaEntity.java
- クラス宣言
class Task → class TaskJpaEntity
- 既存
TaskEntityTest.java(task/adapter/persistence/ 配下、A-2 で移動済)の Task 参照を TaskJpaEntity に追従
- JPA アノテーション・スキーマ・カラム名は変更しない(rename のみ)
4. task/usecase/TaskRepository.java ポート interface 新規
package xyz.dgz48.tasks.webapi.task.usecase;
import java.util.Optional;
import xyz.dgz48.tasks.webapi.task.domain.Task;
public interface TaskRepository {
Optional<Task> findByIdAndTenantId(Long id, Long tenantId);
}
B-2 で必要な最小 method のみ。将来追加は別 Issue で。
5. task/adapter/persistence/TaskJpaRepository.java Spring Data Repository 新規
public interface TaskJpaRepository extends JpaRepository<TaskJpaEntity, Long> {
Optional<TaskJpaEntity> findByIdAndTenantId(Long id, Long tenantId);
}
6. task/adapter/persistence/TaskJpaRepositoryAdapter.java で TaskRepository ポート実装
@Component
TaskJpaRepository を constructor inject
findByIdAndTenantId で Optional<TaskJpaEntity> を Optional<Task> に map
TaskJpaEntity → Task 変換は private method or static factory
やらないこと(B-1 では対象外)
受け入れ条件
参照
A-1 (#86) / A-2 (#272) で整えた 4 層パッケージ上で、
GET /api/tasks/{id}実装の基盤層(shared 例外基底 + JPA Entity / Domain POJO 分離 + Repository ポート)を整備する。N4 (#86) を 7 分割した B-1 スコープ(2026-05-30 Cowork 3 再分割、B が ~18 ファイル / テスト 5 種類で実装 Claude の単一 PR キャパシティ超過の risk あり):
created_by/updated_by列追加 + 統合 IT + AuthZ test 更新 ~3 ファイルやること
1.
shared/exception/配下を新規作成shared/exception/DomainException.javaabstract class DomainException extends RuntimeException、@ResponseStatus禁止、業務例外基底shared/exception/package-info.java@NullMarked2.
task/domain/Task.java(Domain POJO)を新規作成task/adapter/persistence/Task.java(現 JPA Entity)から JPA アノテーション剥離した POJO をtask/domain/に新規:Long id/Long tenantId/String title/String description/Priority priority/TaskStatus status/Visibility visibility/Long assigneeId/LocalDate dueDate/LocalDateTime createdAt/LocalDateTime updatedAt@Entity/@Column/@Id等 JPA 依存禁止、Spring 非依存@Getter+ all-args constructor、equals/hashCode はidベース3.
task/adapter/persistence/Task.javaをTaskJpaEntity.javaに renamegit mv task/adapter/persistence/Task.java task/adapter/persistence/TaskJpaEntity.javaclass Task→class TaskJpaEntityTaskEntityTest.java(task/adapter/persistence/配下、A-2 で移動済)のTask参照をTaskJpaEntityに追従4.
task/usecase/TaskRepository.javaポート interface 新規B-2 で必要な最小 method のみ。将来追加は別 Issue で。
5.
task/adapter/persistence/TaskJpaRepository.javaSpring Data Repository 新規6.
task/adapter/persistence/TaskJpaRepositoryAdapter.javaでTaskRepositoryポート実装@ComponentTaskJpaRepositoryを constructor injectfindByIdAndTenantIdでOptional<TaskJpaEntity>をOptional<Task>に mapTaskJpaEntity → Task変換は private method or static factoryやらないこと(B-1 では対象外)
GetTaskUseCase/TaskController/TaskExceptionHandler/ DTO /TaskNotFoundException/TaskNotViewableException→ B-2 (backend: GET /api/tasks/{id} 4 層実装(UseCase + Controller + DTO + 例外) (N4 / B-2) #278)created_by/updated_by列追加 / 統合 IT /TaskAuthorizationDomainServiceTest更新 → B-3 (backend: DB migration created_by/updated_by + 統合 IT + AuthZ test 更新 (N4 / B-3) #279)受け入れ条件
shared/exception/DomainException.java+package-info.java配置task/domain/Task.java(POJO)新規、JPA 依存なしtask/adapter/persistence/Task.java→TaskJpaEntity.javarename + クラス宣言追従task/usecase/TaskRepository.javaポート(findByIdAndTenantId(Long, Long)のみ)task/adapter/persistence/TaskJpaRepository.java(Spring Data)task/adapter/persistence/TaskJpaRepositoryAdapter.javaでポート実装(JpaEntity → Domain Task 変換含む)TaskEntityTest.javaがTaskJpaEntity名で green./gradlew :webapi:compileJava :webapi:compileTestJavagreen./gradlew :webapi:testgreen、ApplicationModules.verify()green参照