New to Claude Skills? Learn how to install them →

affaan-m on GitHub

JPA/Hibernate Patterns

Free

Optimize your Spring Boot data modeling and performance.

by affaan-m239.3k stars on affaan-m/ecc
5 views
Updated Aug 10, 2026
Get this skill

Free · Opens the source repo

What JPA/Hibernate Patterns does

The JPA/Hibernate Patterns skill provides a comprehensive set of guidelines and code examples for effectively using JPA and Hibernate in Spring Boot applications. It covers essential topics such as entity design, relationship mapping, and query optimization, making it a valuable resource for developers looking to enhance their data access layer. By following the patterns outlined in this skill, you can ensure that your application is not only functional but also efficient and scalable.

This skill is particularly useful for developers who are working with complex data models and need to define relationships between entities. It includes best practices for avoiding common pitfalls like the N+1 query problem, which can severely impact performance. The skill also offers insights into configuring transactions, implementing auditing, and managing pagination, all of which are crucial for maintaining a responsive and robust application.

Additionally, the JPA/Hibernate Patterns skill addresses performance tuning through connection pooling and caching strategies. It provides specific recommendations for configuring HikariCP and using second-level caching effectively. By leveraging these techniques, developers can significantly improve the responsiveness of their applications, especially under load.

Whether you are a seasoned developer or new to Spring Boot, this skill serves as a practical reference for implementing best practices in JPA and Hibernate. It is designed to help you make informed decisions about data modeling and performance optimization, ultimately leading to better application design and user experience.

When to use it

Use this skill when designing JPA entities, optimizing queries, or configuring transactions in Spring Boot applications.

When not to use it

This skill may not be suitable for applications that do not use JPA or Hibernate, or for those requiring non-Spring frameworks.

What you can build with it

Designing a New Entity

Use this skill to define a new JPA entity with proper annotations and indexing for optimal performance.

Optimizing Existing Queries

Refer to the skill when you need to restructure queries to prevent N+1 issues and improve data retrieval efficiency.

Configuring Transaction Management

Utilize the guidelines to set up transaction management in your Spring Boot application for better data integrity and performance.

How to install JPA/Hibernate Patterns

View source

1. Install with the skills CLI

npx skills add affaan-m/ecc/jpa-patterns --agent claude-code

2. Or install it manually

Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.

Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs

Inside SKILL.md

Written by affaan-m

JPA/Hibernate Patterns

Use for data modeling, repositories, and performance tuning in Spring Boot.

When to Activate

  • Designing JPA entities and table mappings
  • Defining relationships (@OneToMany, @ManyToOne, @ManyToMany)
  • Optimizing queries (N+1 prevention, fetch strategies, projections)
  • Configuring transactions, auditing, or soft deletes
  • Setting up pagination, sorting, or custom repository methods
  • Tuning connection pooling (HikariCP) or second-level caching

Entity Design

@Entity
@Table(name = "markets", indexes = {
  @Index(name = "idx_markets_slug", columnList = "slug", unique = true)
})
@EntityListeners(AuditingEntityListener.class)
public class MarketEntity {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @Column(nullable = false, length = 200)
  private String name;

  @Column(nullable = false, unique = true, length = 120)
  private String slug;

  @Enumerated(EnumType.STRING)
  private MarketStatus status = MarketStatus.ACTIVE;

  @CreatedDate private Instant createdAt;
  @LastModifiedDate private Instant updatedAt;
}

Enable auditing:

@Configuration
@EnableJpaAuditing
class JpaConfig {}

Relationships and N+1 Prevention

@OneToMany(mappedBy = "market", cascade = CascadeType.ALL, orphanRemoval = true)
private List<PositionEntity> positions = new ArrayList<>();
  • Default to lazy loading; use JOIN FETCH in queries when needed
  • Avoid EAGER on collections; use DTO projections for read paths
@Query("select distinct m from MarketEntity m left join fetch m.positions where m.id = :id")
Optional<MarketEntity> findWithPositions(@Param("id") Long id);

Note: DISTINCT is required when fetch-joining a one-to-many collection — without it, the root entity is duplicated once per child row in the result set. For single-result queries (findById) the duplication is harmless, but for list queries it produces duplicate root objects. Hibernate 6+ applies de-duplication automatically in some cases, but explicit DISTINCT keeps behavior portable and clear.

Repository Patterns

public interface MarketRepository extends JpaRepository<MarketEntity, Long> {
  Optional<MarketEntity> findBySlug(String slug);

  @Query("select m from MarketEntity m where m.status = :status")
  Page<MarketEntity> findByStatus(@Param("status") MarketStatus status, Pageable pageable);
}
  • Use projections for lightweight queries:
public interface MarketSummary {
  Long getId();
  String getName();
  MarketStatus getStatus();
}
Page<MarketSummary> findAllBy(Pageable pageable);

Transactions

  • Annotate service methods with @Transactional
  • Use @Transactional(readOnly = true) for read paths to optimize
  • Choose propagation carefully; avoid long-running transactions
@Transactional
public Market updateStatus(Long id, MarketStatus status) {
  MarketEntity entity = repo.findById(id)
      .orElseThrow(() -> new EntityNotFoundException("Market"));
  entity.setStatus(status);
  return Market.from(entity);
}

Pagination

PageRequest page = PageRequest.of(pageNumber, pageSize, Sort.by("createdAt").descending());
Page<MarketEntity> markets = repo.findByStatus(MarketStatus.ACTIVE, page);

For cursor-like pagination, include id > :lastId in JPQL with ordering.

Indexing and Performance

  • Add indexes for common filters (status, slug, foreign keys)
  • Use composite indexes matching query patterns (status, created_at)
  • Avoid select *; project only needed columns
  • Batch writes with saveAll and hibernate.jdbc.batch_size

Connection Pooling (HikariCP)

Recommended properties:

spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.validation-timeout=5000

For PostgreSQL LOB handling, add:

spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

Caching

  • 1st-level cache is per EntityManager; avoid keeping entities across transactions
  • For read-heavy entities, consider second-level cache cautiously; validate eviction strategy

Migrations

  • Use Flyway or Liquibase; never rely on Hibernate auto DDL in production
  • Keep migrations idempotent and additive; avoid dropping columns without plan

Testing Data Access

  • Prefer @DataJpaTest with Testcontainers to mirror production
  • Assert SQL efficiency using logs: set logging.level.org.hibernate.SQL=DEBUG and logging.level.org.hibernate.orm.jdbc.bind=TRACE for parameter values

Remember: Keep entities lean, queries intentional, and transactions short. Prevent N+1 with fetch strategies and projections, and index for your read/write paths.

Frequently asked questions about JPA/Hibernate Patterns

Similar skills