
Spring Data Jpa
Scaffold Spring Data JPA entities, relationships, and auditing fields for a CRUD backend the agent can extend without guessing Hibernate mappings.
Overview
Spring Data JPA is an agent skill for the Build phase that provides canonical JPA entity and relationship examples for CRUD Spring Boot backends.
Install
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill spring-data-jpaWhat is this skill?
- Full Example 1 walkthrough: Category and Product entities with @OneToMany / @ManyToOne
- Shows @CreatedDate and @LastModifiedDate auditing columns on Product
- Uses GenerationType.IDENTITY keys, nullable constraints, and precision for money fields
- Demonstrates cascade ALL with orphanRemoval on the parent collection
- Lazy @ManyToOne fetch to avoid accidental N+1 in simple CRUD apps
- Example 1 documents two entity classes: Category and Product
- Demonstrates CascadeType.ALL with orphanRemoval on the parent collection
Adoption & trust: 1.3k installs on skills.sh; 271 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need a correct Category–Product JPA model with auditing and cascades but keep getting broken mappings or eager-load footguns from generic chat answers.
Who is it for?
Solo builders creating Java REST APIs with Spring Data JPA who want a vetted entity-relationship template.
Skip if: Kotlin-only projects, reactive R2DBC stacks, or teams needing querydsl or complex aggregate design without relational CRUD.
When should I use this skill?
User builds Spring Boot persistence with JPA entities, relationships, auditing, or catalog-style CRUD models.
What do I get? / Deliverables
You get working entity classes with IDs, constraints, associations, and auditing field placeholders ready to drop into a Spring Boot module.
- Category and Product @Entity class definitions
- Association mapping pattern for @OneToMany and @ManyToOne
- Column constraint examples for names, TEXT descriptions, and decimal prices
Recommended Skills
Journey fit
Build is where persistence models and repositories land; this skill is reference material for implementing the server-side data layer. Backend subphase covers JPA entities, associations, lazy loading, and timestamp columns typical of production REST services.
How it compares
Entity and mapping cookbook—not a database migration generator or Spring Security setup skill.
Common Questions / FAQ
Who is spring-data-jpa for?
Developers using Claude Code, Cursor, or Codex to build Spring Boot APIs who want JPA entity patterns aligned with common ecommerce-style domains.
When should I use spring-data-jpa?
During Build backend work when defining entities, one-to-many catalogs, or adding @CreatedDate/@LastModifiedDate to new tables.
Is spring-data-jpa safe to install?
It ships example Java only; check Security Audits on this Prism page and review generated code before committing to production schemas.
SKILL.md
READMESKILL.md - Spring Data Jpa
# Spring Data JPA - Code Examples ## Example 1: Simple CRUD Application ### Entity Classes ```java @Entity @Table(name = "categories") public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 100) private String name; @Column(columnDefinition = "TEXT") private String description; @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true) private List<Product> products = new ArrayList<>(); public Category() {} public Category(String name) { this.name = name; } // getters, setters, equals, hashCode } @Entity @Table(name = "products") public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 255) private String name; @Column(precision = 10, scale = 2) private BigDecimal price; @Column(columnDefinition = "INT DEFAULT 0") private Integer stock; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "category_id", nullable = false) private Category category; @CreatedDate @Column(nullable = false, updatable = false) private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; public Product() {} public Product(String name, BigDecimal price, Category category) { this.name = name; this.price = price; this.category = category; } // getters, setters } ``` ### Repository Interfaces ```java @Repository public interface CategoryRepository extends JpaRepository<Category, Long> { Optional<Category> findByName(String name); boolean existsByName(String name); } @Repository public interface ProductRepository extends JpaRepository<Product, Long> { List<Product> findByCategory(Category category); List<Product> findByCategoryAndPriceGreaterThan(Category category, BigDecimal price); Page<Product> findByNameContainingIgnoreCase(String name, Pageable pageable); @Query("SELECT p FROM Product p WHERE p.stock = 0 ORDER BY p.updatedAt DESC") List<Product> findOutOfStockProducts(); @Query("SELECT p FROM Product p WHERE p.price BETWEEN :minPrice AND :maxPrice") List<Product> findByPriceRange( @Param("minPrice") BigDecimal minPrice, @Param("maxPrice") BigDecimal maxPrice ); } ``` ### Service Layer ```java @Service @Transactional public class ProductService { private final ProductRepository productRepository; private final CategoryRepository categoryRepository; public ProductService(ProductRepository productRepository, CategoryRepository categoryRepository) { this.productRepository = productRepository; this.categoryRepository = categoryRepository; } @Transactional(readOnly = true) public Page<Product> searchProducts(String query, int page, int size) { Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending()); return productRepository.findByNameContainingIgnoreCase(query, pageable); } @Transactional(readOnly = true) public List<Product> getProductsByCategory(Long categoryId) { Category category = categoryRepository.findById(categoryId) .orElseThrow(() -> new CategoryNotFoundException(categoryId)); return productRepository.findByCategory(category); } @Transactional(readOnly = true) public List<Product> getExpensiveProducts(Long categoryId, BigDecimal minPrice) { Category category = categoryRepository.findById(categoryId) .orElseThrow(() -> new CategoryNotFoundException(categoryId)); return productRepository.findByCategoryAndPriceGreaterThan(category, minPrice); } public Product createProduct(CreateProductRequest request) { Category categ