Loading...
Loading...
Master JPA/Hibernate - entity design, queries, transactions, performance optimization
npx skill4agent add pluginagentmarketplace/custom-plugin-java java-jpa-hibernate// Entity with relationships
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
@BatchSize(size = 20)
private List<OrderItem> items = new ArrayList<>();
@Version
private Long version;
// Bidirectional helper
public void addItem(OrderItem item) {
items.add(item);
item.setOrder(this);
}
}
// Auditing base class
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {
@CreatedDate
@Column(updatable = false)
private Instant createdAt;
@LastModifiedDate
private Instant updatedAt;
}
// Repository with query optimization
public interface OrderRepository extends JpaRepository<Order, Long> {
// JOIN FETCH to prevent N+1
@Query("SELECT DISTINCT o FROM Order o JOIN FETCH o.items WHERE o.status = :status")
List<Order> findByStatusWithItems(@Param("status") Status status);
// EntityGraph alternative
@EntityGraph(attributePaths = {"items", "customer"})
Optional<Order> findById(Long id);
// DTO Projection
@Query("SELECT new com.example.OrderSummary(o.id, o.status, c.name) " +
"FROM Order o JOIN o.customer c WHERE o.id = :id")
Optional<OrderSummary> findSummaryById(@Param("id") Long id);
}| Strategy | Use When | Example |
|---|---|---|
| JOIN FETCH | Always need relation | |
| EntityGraph | Dynamic fetching | |
| @BatchSize | Collection access | |
| DTO Projection | Read-only queries | |
spring:
jpa:
open-in-view: false # Critical!
properties:
hibernate:
jdbc.batch_size: 50
order_inserts: true
order_updates: true
default_batch_fetch_size: 20
generate_statistics: ${HIBERNATE_STATS:false}
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
leak-detection-threshold: 60000| Problem | Cause | Solution |
|---|---|---|
| N+1 queries | Lazy in loop | JOIN FETCH, EntityGraph |
| LazyInitException | Session closed | DTO projection |
| Slow queries | Missing index | EXPLAIN ANALYZE |
| Connection leak | No @Transactional | Add annotation |
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.orm.jdbc.bind=TRACE
hibernate.generate_statistics=true□ Enable SQL logging
□ Check query count per request
□ Verify fetch strategies
□ Review @Transactional
□ Check connection poolSkill("java-jpa-hibernate")java-performancejava-spring-boot