Marketplace

spring-data-jpa

Master Spring Data JPA - repositories, queries, relationships, transactions, and performance

$ 安裝

git clone https://github.com/pluginagentmarketplace/custom-plugin-spring-boot /tmp/custom-plugin-spring-boot && cp -r /tmp/custom-plugin-spring-boot/skills/spring-data-jpa ~/.claude/skills/custom-plugin-spring-boot

// tip: Run this command in your terminal to install the skill


name: spring-data-jpa description: Master Spring Data JPA - repositories, queries, relationships, transactions, and performance sasmp_version: "1.3.0" bonded_agent: 03-spring-data bond_type: PRIMARY_BOND version: "2.0.0" updated: "2024-12-30"

Spring Data JPA Skill

Comprehensive guide to data access with Spring Data JPA including repository patterns, custom queries, and performance optimization.

Overview

This skill covers everything needed for production-ready database access with Spring Data JPA.

Parameters

NameTypeRequiredDefaultValidation
databaseenumpostgresqlpostgresql | mysql | h2
migration_toolenumflywayflyway | liquibase | none
fetch_strategyenumlazylazy | eager

Topics Covered

Core (Must Know)

  • Entities: @Entity, @Table, @Id, relationships
  • Repositories: JpaRepository, derived queries
  • Transactions: @Transactional, propagation

Intermediate

  • Custom Queries: @Query with JPQL and native SQL
  • Projections: Interface-based, class-based
  • Auditing: @CreatedDate, @LastModifiedDate

Advanced

  • Specifications: Dynamic query building
  • Entity Graphs: Fetch optimization
  • N+1 Prevention: JOIN FETCH strategies

Code Examples

Entity with Relationships

@Entity
@Table(name = "orders")
@EntityListeners(AuditingEntityListener.class)
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String orderNumber;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id", nullable = false)
    private Customer customer;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items = new ArrayList<>();

    @CreatedDate
    private LocalDateTime createdAt;

    @Version
    private Long version;

    public void addItem(OrderItem item) {
        items.add(item);
        item.setOrder(this);
    }
}

Repository with Custom Queries

public interface OrderRepository extends JpaRepository<Order, Long>,
                                         JpaSpecificationExecutor<Order> {

    Optional<Order> findByOrderNumber(String orderNumber);

    @Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.customer.id = :customerId")
    List<Order> findByCustomerWithItems(@Param("customerId") Long customerId);

    @EntityGraph(attributePaths = {"items", "customer"})
    Optional<Order> findWithDetailsById(Long id);

    @Modifying
    @Query("UPDATE Order o SET o.status = :status WHERE o.id = :id")
    int updateStatus(@Param("id") Long id, @Param("status") OrderStatus status);
}

Specification Pattern

public class OrderSpecifications {

    public static Specification<Order> hasStatus(OrderStatus status) {
        return (root, query, cb) ->
            status == null ? null : cb.equal(root.get("status"), status);
    }

    public static Specification<Order> createdAfter(LocalDateTime date) {
        return (root, query, cb) ->
            date == null ? null : cb.greaterThan(root.get("createdAt"), date);
    }
}

// Usage
Specification<Order> spec = Specification
    .where(OrderSpecifications.hasStatus(status))
    .and(OrderSpecifications.createdAfter(since));
Page<Order> orders = orderRepository.findAll(spec, pageable);

Troubleshooting

Failure Modes

IssueDiagnosisFix
N+1 queriesMultiple SELECTsUse @EntityGraph or JOIN FETCH
LazyInitializationExceptionAccess outside sessionUse @Transactional or DTO
Data not savedMissing @TransactionalAdd to service method

Debug Checklist

□ Enable SQL logging: spring.jpa.show-sql=true
□ Check for N+1 with hibernate.generate_statistics
□ Verify @Transactional on write operations
□ Review fetch types (LAZY vs EAGER)

Unit Test Template

@DataJpaTest
@Testcontainers
class OrderRepositoryTest {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");

    @Autowired
    private OrderRepository orderRepository;

    @Test
    void shouldFindByOrderNumber() {
        Order order = new Order();
        order.setOrderNumber("ORD-001");
        orderRepository.save(order);

        Optional<Order> found = orderRepository.findByOrderNumber("ORD-001");
        assertThat(found).isPresent();
    }
}

Usage

Skill("spring-data-jpa")

Version History

VersionDateChanges
2.0.02024-12-30Specifications, auditing, performance patterns
1.0.02024-01-01Initial release