
Java Architect
Model Spring/JPA entities with indexes, lazy loading, caching, and relationship mapping instead of guessing Hibernate defaults.
Overview
Java Architect is an agent skill for the Build phase that guides optimized JPA/Hibernate entity and relationship design for Spring-backed APIs.
Install
npx skills add https://github.com/jeffallan/claude-skills --skill java-architectWhat is this skill?
- JPA entity templates with indexes, auditing listeners, and second-level cache hints
- Relationship mapping with LAZY fetch, @BatchSize, cascade, and orphan removal on collections
- Lombok builder/getter patterns aligned with Spring Data JPA conventions
- Table-level index definitions for hot query columns (email, created_at)
Adoption & trust: 3.7k installs on skills.sh; 9.7k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are adding Java domain models but your agent keeps generating eager-loaded graphs, missing indexes, and relationship mappings that will hurt queries later.
Who is it for?
Indie builders on Spring Boot who want agent-generated JPA entities to match common production Hibernate practices on the first pass.
Skip if: Teams that only need raw SQL tuning, non-JVM stacks, or a full system architecture review without entity-level JPA detail.
When should I use this skill?
Implementing or refactoring Java domain entities with JPA/Hibernate on a Spring-style backend.
What do I get? / Deliverables
You get copy-ready entity patterns with lazy associations, batch sizing, auditing, caching, and index declarations suited for a maintainable backend schema.
- Optimized @Entity class patterns
- Relationship mapping with fetch and cascade rules
- Index and cache annotation guidance
Recommended Skills
Journey fit
Canonical shelf is Build because the skill ships production-grade persistence-layer patterns (entities, JPA mappings) during backend implementation. Backend subphase fits ORM entity design, fetch strategies, and schema-adjacent Java domain modeling.
How it compares
Use for concrete JPA entity blueprints instead of generic “write a User class” chat without fetch and index guardrails.
Common Questions / FAQ
Who is java-architect for?
Solo and small-team developers shipping Java/Spring services who want structured JPA entity and mapping guidance from their coding agent.
When should I use java-architect?
During Build/backend work when defining entities, fixing N+1-prone relationships, or aligning indexes and lazy loading before you merge persistence code.
Is java-architect safe to install?
Review the Security Audits panel on this Prism page and inspect the skill package in your repo before granting agent filesystem or shell access.
SKILL.md
READMESKILL.md - Java Architect
# JPA Optimization ## Optimized Entity Design ```java package com.example.domain.model; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.Instant; import java.util.ArrayList; import java.util.List; @Entity @Table( name = "users", indexes = { @Index(name = "idx_email", columnList = "email"), @Index(name = "idx_created_at", columnList = "created_at") } ) @EntityListeners(AuditingEntityListener.class) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true, length = 100) private String email; @Column(nullable = false, length = 50) private String username; @Column(nullable = false) private Boolean active = true; @OneToMany( mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY ) @BatchSize(size = 25) @Builder.Default private List<Order> orders = new ArrayList<>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "department_id") private Department department; @CreatedDate @Column(nullable = false, updatable = false) private Instant createdAt; @LastModifiedDate private Instant updatedAt; @Version private Long version; // Helper methods public void addOrder(Order order) { orders.add(order); order.setUser(this); } public void removeOrder(Order order) { orders.remove(order); order.setUser(null); } } ``` ## Repository with Custom Queries ```java package com.example.domain.repository; import com.example.domain.model.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.repository.query.Param; import java.time.Instant; import java.util.List; import java.util.Optional; public interface UserRepository extends JpaRepository<User, Long> { // N+1 prevention with EntityGraph @EntityGraph(attributePaths = {"orders", "department"}) @Query("SELECT u FROM User u WHERE u.id = :id") Optional<User> findByIdWithOrders(@Param("id") Long id); // Projection for read-only queries @Query(""" SELECT new com.example.application.dto.UserSummary( u.id, u.email, u.username, COUNT(o) ) FROM User u LEFT JOIN u.orders o WHERE u.active = true GROUP BY u.id, u.email, u.username """) List<UserSummary> findActiveUsersSummary(); // Fetch join to avoid N+1 @Query(""" SELECT DISTINCT u FROM User u LEFT JOIN FETCH u.orders WHERE u.department.id = :deptId """) List<User> findByDepartmentWithOrders(@Param("deptId") Long deptId); // Pagination with count query optimization @Query( value = "SELECT u FROM User u WHERE u.active = true", countQuery = "SELECT COUNT(u) FROM User u WHERE u.active = true" ) Page<User> findActiveUsers(Pageable pageable); // Batch update @Modifying @Query("UPDATE User u SET u.active = false WHERE u.createdAt < :date") int deactivateOldUsers(@Param("date") Instant date); // Native query for complex operations @Query( value = """ SE