Hibernate ORM Setup for Java Web Application
Hibernate — JPA specification implementation with rich extensions. In modern Spring Boot 3.x projects, Hibernate 6.x is used through Spring Data JPA, but understanding the Hibernate layer directly is necessary for fine-tuning performance, custom types, and complex mappings.
Dependencies (Maven)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
Configuration
spring:
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
hibernate:
ddl-auto: validate
properties:
hibernate:
jdbc:
batch_size: 50
order_inserts: true
cache:
use_second_level_cache: true
region.factory_class: org.hibernate.cache.jcache.JCacheCacheRegionFactory
Entity
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(nullable = false, length = 500)
private String title;
@Column(unique = true, nullable = false)
private String slug;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private ProductStatus status = ProductStatus.DRAFT;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "category_id")
private Category category;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "product_tags",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private Set<Tag> tags = new HashSet<>();
@CreationTimestamp
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
}
Spring Data JPA Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
@Query("""
SELECT p FROM Product p
JOIN FETCH p.category
WHERE p.status = :status
ORDER BY p.createdAt DESC
""")
List<Product> findPublishedWithCategory(@Param("status") ProductStatus status);
@EntityGraph(attributePaths = {"category", "tags"})
List<Product> findByStatus(ProductStatus status);
}
N+1 Prevention
Use @EntityGraph or JOIN FETCH to prevent N+1 queries. Set FetchType.LAZY on @ManyToOne — it's critical for performance.
@BatchSize(size = 20)
@ManyToMany
private Set<Tag> tags;
Flyway Migrations
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
Files: V1__create_products.sql, V2__add_index.sql.
Timeline
Initial Spring Boot + Hibernate setup: 1–2 days. Performance optimization: 2–4 days.







