Skip to content

backend: 基盤(shared/exception + Task POJO/JPA Entity 分離 + Repository ポート) (N4 / B-1) #273

Description

@win2cot

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 アノテーション剥離した POJOtask/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.javaTaskJpaEntity.java に rename

  • git mv task/adapter/persistence/Task.java task/adapter/persistence/TaskJpaEntity.java
  • クラス宣言 class Taskclass 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.javaTaskRepository ポート実装

  • @Component
  • TaskJpaRepository を constructor inject
  • findByIdAndTenantIdOptional<TaskJpaEntity>Optional<Task> に map
  • TaskJpaEntity → Task 変換は private method or static factory

やらないこと(B-1 では対象外)

受け入れ条件

  • shared/exception/DomainException.java + package-info.java 配置
  • task/domain/Task.java(POJO)新規、JPA 依存なし
  • task/adapter/persistence/Task.javaTaskJpaEntity.java rename + クラス宣言追従
  • task/usecase/TaskRepository.java ポート(findByIdAndTenantId(Long, Long) のみ)
  • task/adapter/persistence/TaskJpaRepository.java(Spring Data)
  • task/adapter/persistence/TaskJpaRepositoryAdapter.java でポート実装(JpaEntity → Domain Task 変換含む)
  • 既存 TaskEntityTest.javaTaskJpaEntity 名で green
  • ./gradlew :webapi:compileJava :webapi:compileTestJava green
  • ./gradlew :webapi:test green、ApplicationModules.verify() green
  • CI green、UT カバレッジ 80%+

参照

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/backendJava / Spring バックエンド実装変更priority/p1High。現スプリント内で完了必須

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions