Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

spring-boot-crud-patterns

Spring Boot 3サービス向けの完全なCRUDワークフローを提供・生成するスキルです。Spring Data JPAのアグリゲート、リポジトリ、DTO、コントローラー、REST APIを備えたフィーチャー指向アーキテクチャを構築し、ドメイン不変条件とトランザクション境界の検証も行います。JavaバックエンドサービスやREST APIエンドポイントの設計、データベース操作、JPAエンティティのモデリングなど、Spring Bootアプリケーション開発全般で活用できます。

description の原文を見る

Provides and generates complete CRUD workflows for Spring Boot 3 services. Creates feature-focused architecture with Spring Data JPA aggregates, repositories, DTOs, controllers, and REST APIs. Validates domain invariants and transaction boundaries. Use when modeling Java backend services, REST API endpoints, database operations, web service patterns, or JPA entities for Spring Boot applications.

SKILL.md 本文

Spring Boot CRUD パターン

概要

機能中心のアーキテクチャを使用したSpring Boot 3.5+サービス向けの完全なCRUDワークフローを提供します。ドメイン集約、JPAリポジトリ、アプリケーションサービス、RESTコントローラーを作成・検証し、適切な関心の分離を実現します。段階的な情報公開のため、詳細なコード一覧は参照ファイルに記載します。

使用タイミング

  • Spring Data JPAで支援されたcreate/read/update/deleteワークフロー向けのRESTエンドポイントを作成する。
  • 集約、リポジトリ、アプリケーションサービスを備えたDDD着想のアーキテクチャに従う機能パッケージを実装する。
  • DTOレコード、リクエスト検証、外部クライアント向けのコントローラーマッピングを定義する。
  • 既存Spring Bootサービスのcrud回帰、リポジトリコントラクト、またはトランザクション境界を診断する。
  • トリガーフレーズ: 「Spring CRUDコントローラーを実装」「エンドポイントを作成」「データベースエンティティを追加」「機能ベースのリポジトリを改良」「JPA集約向けDTOをマッピング」「REST listエンドポイントにページネーションを追加」

手順

以下の合理化されたワークフローに従って、明示的な検証ゲートを備えた機能整合的なCRUDサービスを提供します:

1. 機能構造を確立

feature/<name>/ ディレクトリを作成し、domainapplicationpresentationinfrastructure サブパッケージを含めます。 検証: 機能境界と一致するディレクトリ構造を確認してから進めます。

2. ドメインモデルを定義

ファクトリメソッド(createupdate)を通じて不変条件を適用するエンティティクラスを作成します。ドメインロジックはフレームワークに依存しないようにします。 検証: すべての不変条件が単体テストでカバーされていることを確認してから進めます。

3. ドメインポートを公開

実装詳細なしに永続化コントラクトを記述する、domain/repository 内のリポジトリインターフェースを宣言します。 検証: インターフェースシグネチャがドメイン操作と一致することを確認します。

4. インフラストラクチャアダプターを提供

infrastructure/persistence 内のJPAエンティティを作成し、ドメインモデルにマップします。Spring Dataリポジトリを実装します。 検証: @DataJpaTest を実行してエンティティマッピングとリポジトリ統合を検証します。

5. アプリケーションサービスを実装

ドメイン操作とDTOマッピングを編成する @Transactional サービスクラスを作成します。 検証: トランザクション境界が正しく、必要に応じて楽観的ロックが適用されていることを確認します。

6. DTOとコントローラーを定義

jakarta.validation アノテーション付きのJavaレコードをAPI契約として使用します。適切なステータスコードでRESTエンドポイントをマップします。 検証: 検証制約をテストし、HTTPステータスコード (201 POST、200 GET、204 DELETE) を検証します。

7. 検証とデプロイ

Testcontainersで統合テストを実行します。マイグレーション (Liquibase/Flyway) が集約スキーマを反映していることを検証します。 検証: デプロイ前に完全なテストスイートを実行し、スキーママイグレーションスクリプトが適用されていることを確認します。

各ステップに合わせた完全なコードについては references/examples-product-feature.md を参照してください。

Javaコード例: Product機能

// feature/product/domain/Product.java
package com.example.product.domain;

import java.math.BigDecimal;
import java.time.Instant;

public record Product(
    String id,
    String name,
    String description,
    BigDecimal price,
    int stock,
    Instant createdAt,
    Instant updatedAt
) {
    public static Product create(String name, String desc, BigDecimal price, int stock) {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required");
        if (price == null || price.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException("Invalid price");
        return new Product(null, name.trim(), desc, price, stock, Instant.now(), null);
    }

    public Product withPrice(BigDecimal newPrice) {
        return new Product(id, name, description, newPrice, stock, createdAt, Instant.now());
    }
}
// feature/product/domain/repository/ProductRepository.java
package com.example.product.domain.repository;

import com.example.product.domain.Product;
import java.util.Optional;

public interface ProductRepository {
    Product save(Product product);
    Optional<Product> findById(String id);
    void deleteById(String id);
}
// feature/product/infrastructure/persistence/ProductJpaEntity.java
package com.example.product.infrastructure.persistence;

import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.Instant;

@Entity @Table(name = "products")
public class ProductJpaEntity {
    @Id @GeneratedValue(strategy = GenerationType.UUID)
    private String id;
    private String name;
    private String description;
    private BigDecimal price;
    private int stock;
    private Instant createdAt;
    private Instant updatedAt;

    // getters, setters, constructor from domain (omitted for brevity)
}
// feature/product/infrastructure/persistence/JpaProductRepository.java
package com.example.product.infrastructure.persistence;

import com.example.product.domain.Product;
import com.example.product.domain.repository.ProductRepository;
import org.springframework.stereotype.Repository;

@Repository
public class JpaProductRepository implements ProductRepository {
    private final SpringDataProductRepository springData;

    public JpaProductRepository(SpringDataProductRepository springData) {
        this.springData = springData;
    }

    @Override
    public Product save(Product product) {
        ProductJpaEntity entity = toEntity(product);
        ProductJpaEntity saved = springData.save(entity);
        return toDomain(saved);
    }

    // findById, deleteById implementations...
}
// feature/product/presentation/rest/ProductController.java
package com.example.product.presentation.rest;

import com.example.product.domain.Product;
import com.example.product.domain.repository.ProductRepository;
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController @RequestMapping("/api/products")
public class ProductController {
    private final ProductService service;

    public ProductController(ProductService service) { this.service = service; }

    @PostMapping
    public ResponseEntity<ProductResponse> create(@Valid @RequestBody CreateProductRequest req) {
        Product product = service.create(req.toDomain());
        return ResponseEntity.status(201).body(ProductResponse.from(product));
    }

    @GetMapping("/{id}")
    public ResponseEntity<ProductResponse> getById(@PathVariable String id) {
        return service.findById(id)
            .map(p -> ResponseEntity.ok(ProductResponse.from(p)))
            .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable String id) {
        service.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    // record DTOs
    public record CreateProductRequest(
        @NotBlank String name,
        String description,
        @NotNull @DecimalMin("0.01") java.math.BigDecimal price,
        @Min(0) int stock
    ) {
        Product toDomain() { return Product.create(name, description, price, stock); }
    }

    public record ProductResponse(String id, String name, java.math.BigDecimal price) {
        static ProductResponse from(Product p) { return new ProductResponse(p.id(), p.name(), p.price()); }
    }
}

JSONの入出力例

作成リクエスト:

{
  "name": "Wireless Keyboard",
  "description": "Ergonomic keyboard",
  "price": 79.99,
  "stock": 50
}

作成レスポンス (201):

{
  "id": "prod-123",
  "name": "Wireless Keyboard",
  "price": 79.99,
  "_links": { "self": "/api/products/prod-123" }
}

ページネーション付きlistリクエスト:

curl "http://localhost:8080/api/products?page=0&size=10&sort=name,asc"

ベストプラクティス

  • ドメイン、アプリケーション、プレゼンテーションコードを機能パッケージ内の集約ごとに共存させる。
  • 不変DTOとしてJavaレコードを使用し、サービス境界でドメイン型を変換する。
  • 書き込み操作にトランザクションと楽観的ロックを適用する。
  • ページネーションのデフォルト (page、size、sort) を正規化し、クエリパラメーターを文書化する。
  • CRUD ライフサイクルイベント (create、update、delete) を情報レベルでログし、構造化された監査証跡を保つ。
  • Spring Boot Actuator を通じてヘルスとメトリクスを公開し、スループットとエラー率を監視する。

制約と警告

  • 決して JPAエンティティをコントローラーに直接公開しないでください。遅延ローディングのリークとシリアライゼーション問題を防ぎます。
  • 決して フィールドインジェクションとコンストラクターインジェクションを混在させないでください。テスト性のための不変性を保つ。
  • 決して ビジネスロジックをコントローラーまたはリポジトリアダプターに埋め込まないでください。ドメイン/アプリケーションレイヤーに保つ。
  • 常に 制約違反を防ぎ、一貫したエラーペイロードを生成するため、入力を積極的に検証します。
  • 常に スキーマ変更をデプロイする前に、マイグレーション (Liquibase/Flyway) が集約の進化を反映していることを確認してください。
  • 常に マージ前にTestcontainersで統合テストを実行し、永続化の回帰を防ぎます。

参考資料

  • HTTPメソッド、アノテーション、DTOパターン
  • スターターから高度な例への段階的な例
  • Spring Boot公式ドキュメント
  • CRUDジェネレータースクリプト - python scripts/generate_crud_boilerplate.py --spec entity.json --package com.example.product --output ./generated

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
giuseppe-trisciuoglio
リポジトリ
giuseppe-trisciuoglio/developer-kit
ライセンス
MIT
最終更新
不明

Source: https://github.com/giuseppe-trisciuoglio/developer-kit / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: giuseppe-trisciuoglio · giuseppe-trisciuoglio/developer-kit · ライセンス: MIT