LearnThatStack Ace your next interview

Hibernate.
Interview cheat sheet.

Quick reference for Hibernate - sectioned for fast scanning. Skim the part you're shaky on, walk in confident.

Backend Development 18-section reference ~11 min read

Summary

Hibernate is a powerful Object-Relational Mapping (ORM) framework for Java that simplifies database interactions by mapping Java objects to database tables. This cheatsheet covers core Hibernate concepts including configuration, entity mapping, relationships, caching strategies, query methods (HQL, Criteria API, Native SQL), transaction management, performance optimization, and best practices. Key features include automatic dirty checking, lazy loading, multi-level caching, database independence through dialects, and seamless integration with Spring Framework.

1. Core Concepts

What is Hibernate?

  • ORM (Object-Relational Mapping) framework for Java
  • Maps Java objects to database tables
  • Eliminates boilerplate JDBC code
  • Database-independent through dialect system

Key Components

  • SessionFactory: Thread-safe, heavyweight object (one per application)
  • Session: Single-threaded, lightweight (one per transaction)
  • Transaction: Unit of work
  • Query: HQL/Criteria/Native SQL execution

2. Configuration

XML Configuration (hibernate.cfg.xml)

<hibernate-configuration>
  <session-factory>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/db</property>
    <property name="connection.username">root</property>
    <property name="connection.password">pass</property>
    <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
    <property name="show_sql">true</property>
    <property name="hbm2ddl.auto">update</property>
    <mapping class="com.example.Employee"/>
  </session-factory>
</hibernate-configuration>

Java Configuration

Configuration cfg = new Configuration()
    .setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/db")
    .setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect")
    .addAnnotatedClass(Employee.class);
SessionFactory factory = cfg.buildSessionFactory();

3. Entity Mapping

Basic Entity

@Entity
@Table(name = "employees")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "emp_name", nullable = false, length = 50)
    private String name;
    
    @Temporal(TemporalType.DATE)
    private Date joinDate;
    
    @Transient
    private String tempData; // Not persisted
}

ID Generation Strategies

  • AUTO: Let Hibernate pick
  • IDENTITY: Auto-increment column
  • SEQUENCE: Database sequence
  • TABLE: Separate table for IDs
  • UUID: Universally unique identifier

4. Relationships

One-to-One

@Entity
public class Employee {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "address_id")
    private Address address;
}

One-to-Many / Many-to-One

@Entity
public class Department {
    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
    private List<Employee> employees;
}

@Entity
public class Employee {
    @ManyToOne
    @JoinColumn(name = "dept_id")
    private Department department;
}

Many-to-Many

@Entity
public class Student {
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private Set<Course> courses;
}

5. Fetch Types & Cascade

Fetch Types

  • EAGER: Load immediately (default for @OneToOne, @ManyToOne)
  • LAZY: Load on demand (default for @OneToMany, @ManyToMany)
@OneToMany(fetch = FetchType.LAZY)
private List<Order> orders;

Cascade Types

  • ALL: All operations
  • PERSIST: Save operations
  • MERGE: Update operations
  • REMOVE: Delete operations
  • REFRESH: Reload operations
  • DETACH: Detach operations

6. Session Operations

CRUD Operations

// Create
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
session.save(employee);
tx.commit();

// Read
Employee emp = session.get(Employee.class, 1L); // Returns null if not found
Employee emp2 = session.load(Employee.class, 1L); // Throws exception if not found

// Update
emp.setName("New Name");
session.update(emp);

// Delete
session.delete(emp);

// Merge (for detached objects)
session.merge(emp);

7. Object States

  1. Transient: New object, not associated with session
  2. Persistent: Associated with session, tracked for changes
  3. Detached: Was persistent, session closed
  4. Removed: Marked for deletion
Employee emp = new Employee(); // Transient
session.save(emp); // Persistent
session.close(); // Detached
session2.merge(emp); // Persistent again

8. Query Methods

HQL (Hibernate Query Language)

// Basic query
Query<Employee> query = session.createQuery("FROM Employee", Employee.class);
List<Employee> employees = query.list();

// With parameters
Query<Employee> query = session.createQuery(
    "FROM Employee WHERE salary > :sal", Employee.class);
query.setParameter("sal", 50000);

// Named parameters
Query<Employee> query = session.createQuery(
    "FROM Employee e WHERE e.name = :name AND e.dept = :dept");
query.setParameter("name", "John");
query.setParameter("dept", "IT");

Criteria API

CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Employee> cr = cb.createQuery(Employee.class);
Root<Employee> root = cr.from(Employee.class);

// Simple query
cr.select(root);

// With conditions
cr.select(root).where(cb.gt(root.get("salary"), 50000));

// Multiple conditions
Predicate salaryPredicate = cb.gt(root.get("salary"), 50000);
Predicate deptPredicate = cb.equal(root.get("department"), "IT");
cr.where(cb.and(salaryPredicate, deptPredicate));

List<Employee> results = session.createQuery(cr).getResultList();

Native SQL

NativeQuery<Employee> query = session.createNativeQuery(
    "SELECT * FROM employees WHERE salary > :sal", Employee.class);
query.setParameter("sal", 50000);
List<Employee> employees = query.list();

9. Named Queries

Define Named Query

@Entity
@NamedQuery(
    name = "Employee.findByDepartment",
    query = "FROM Employee e WHERE e.department = :dept"
)
@NamedNativeQuery(
    name = "Employee.findHighSalary",
    query = "SELECT * FROM employees WHERE salary > 100000",
    resultClass = Employee.class
)
public class Employee { }

Use Named Query

Query<Employee> query = session.createNamedQuery(
    "Employee.findByDepartment", Employee.class);
query.setParameter("dept", "IT");

10. Caching

First Level Cache (Session Cache)

  • Enabled by default
  • Session-scoped
  • Automatic
Employee emp1 = session.get(Employee.class, 1L); // Database hit
Employee emp2 = session.get(Employee.class, 1L); // No database hit

Second Level Cache

  • SessionFactory-scoped
  • Requires configuration
  • Use @Cacheable and @Cache annotations
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee { }

Query Cache

<property name="cache.use_query_cache">true</property>
Query query = session.createQuery("FROM Employee");
query.setCacheable(true);

11. Transactions

Transaction Management

Transaction tx = null;
try {
    tx = session.beginTransaction();
    // Operations
    tx.commit();
} catch (Exception e) {
    if (tx != null) tx.rollback();
    throw e;
} finally {
    session.close();
}

Isolation Levels

  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE

12. Performance Optimization

N+1 Problem Solution

// Problem: N+1 queries
List<Department> depts = session.createQuery("FROM Department").list();
for (Department dept : depts) {
    dept.getEmployees().size(); // Additional query for each department
}

// Solution 1: Join Fetch
List<Department> depts = session.createQuery(
    "FROM Department d JOIN FETCH d.employees").list();

// Solution 2: Batch Fetching
@BatchSize(size = 10)
private List<Employee> employees;

Pagination

Query<Employee> query = session.createQuery("FROM Employee", Employee.class);
query.setFirstResult(20); // Offset
query.setMaxResults(10);  // Limit

Projection

// Select specific columns
List<Object[]> results = session.createQuery(
    "SELECT e.name, e.salary FROM Employee e").list();

13. Best Practices

1. Session Management

  • Keep sessions short-lived
  • One session per request/transaction
  • Always close sessions

2. Use Lazy Loading

@OneToMany(fetch = FetchType.LAZY)
private List<Order> orders;

3. Batch Processing

for (int i = 0; i < 100000; i++) {
    session.save(new Employee());
    if (i % 50 == 0) { // Batch size
        session.flush();
        session.clear();
    }
}

4. Use Appropriate Cascade

  • Don't use CascadeType.ALL everywhere
  • Be specific about cascade operations

5. Avoid SELECT N+1

  • Use JOIN FETCH for eager loading
  • Use @BatchSize for collections

14. Common Annotations

Annotation Purpose
@Entity Mark class as entity
@Table Specify table details
@Id Primary key
@GeneratedValue ID generation strategy
@Column Column mapping
@Transient Skip field
@Temporal Date/Time type
@Lob Large objects
@Enumerated Enum mapping
@Embedded Embedded object
@Version Optimistic locking

15. Key Concepts & Comparisons

Core Methods Comparison

Method Purpose Database Hit Use Case Return Value
get() Load entity Immediate When you need null check Entity or null
load() Load entity proxy Lazy (when accessed) When entity exists Proxy (exception if not found)
save() Insert entity At flush/commit New entities Generated ID
persist() Make entity persistent At flush/commit New entities in transaction void
update() Update detached entity At flush/commit Known detached entities void
merge() Copy state to persistent At flush/commit Detached entities (safe) Persistent entity
saveOrUpdate() Save or update At flush/commit Unknown entity state Generated ID if new

Session vs SessionFactory

Aspect Session SessionFactory
Thread Safety Not thread-safe Thread-safe
Lifecycle Short-lived (per transaction) Long-lived (application scope)
Weight Lightweight Heavyweight
Creation Cost Low High
Instances Many per application One per application
Purpose Unit of work interface Factory for sessions

Fetch Type Strategies

Fetch Type When Loaded Default For Use Case Performance Impact
EAGER Immediately with parent @OneToOne, @ManyToOne Small related data Higher memory, fewer queries
LAZY On first access @OneToMany, @ManyToMany Large collections Lower memory, more queries

Cascade Type Options

Cascade Type Operations Included Use Case Risk Level
PERSIST Save operations Parent-child creation Low
MERGE Update operations Detached entity updates Low
REMOVE Delete operations Dependent entity cleanup High
REFRESH Reload operations Data synchronization Low
DETACH Detach operations Session management Low
ALL All above operations Complete lifecycle management Very High

ID Generation Strategy Comparison

Strategy How It Works Database Support Use Case
AUTO Hibernate chooses best All databases Default choice
IDENTITY Auto-increment column MySQL, SQL Server Single database
SEQUENCE Database sequence PostgreSQL, Oracle High performance
TABLE Separate ID table All databases Portability needed
UUID Universal unique ID All databases Distributed systems

Object State Transitions

// State transition examples
Employee emp = new Employee();           // TRANSIENT
session.save(emp);                      // PERSISTENT
session.close();                        // DETACHED
session2.delete(emp);                   // REMOVED (if reattached)
State Description Session Association Database Sync
Transient New object, not in database No No
Persistent Managed by session Yes Yes (at flush)
Detached Was persistent, session closed No No
Removed Marked for deletion Yes Yes (at flush)

Query Method Comparison

Query Type Syntax Type Safety Performance Use Case
HQL String-based Runtime Good Simple to complex queries
Criteria API Object-oriented Compile-time Good Dynamic query building
Native SQL Database-specific None Best Database-specific features
Named Queries Predefined HQL/SQL Runtime Best (parsed once) Reusable queries

Caching Levels

Cache Level Scope Configuration Use Case Performance Impact
First Level Session Automatic Single transaction Eliminates repeated gets
Second Level SessionFactory Manual setup Cross-session Reduces database load
Query Cache SessionFactory Requires configuration Repeated queries Caches query results

Dialect Examples

Database Dialect Class Features
MySQL MySQL5Dialect, MySQL8Dialect Auto-increment, specific functions
PostgreSQL PostgreSQLDialect Sequences, advanced types
Oracle OracleDialect Sequences, hierarchical queries
SQL Server SQLServerDialect Identity columns, T-SQL
H2 H2Dialect In-memory, testing

Performance Optimization Strategies

Problem Solution Implementation Impact
N+1 Queries JOIN FETCH JOIN FETCH in HQL Reduces query count
Large Collections Batch Fetching @BatchSize(size=10) Optimizes lazy loading
Memory Usage Lazy Loading fetch=FetchType.LAZY Reduces memory footprint
Bulk Operations Batch Processing flush() and clear() every N records Prevents memory issues
Read Performance Second Level Cache @Cacheable + cache config Reduces database hits

Common Exceptions & Solutions

Exception Cause Solution
LazyInitializationException Accessing lazy property after session close Use JOIN FETCH or Open Session in View
NonUniqueObjectException Duplicate object in session Use merge() instead of update()
StaleObjectStateException Optimistic locking conflict Handle version conflicts in application
ConstraintViolationException Database constraint violation Validate data before persisting

Architecture Layers

┌─────────────────────────────────────┐
│         Application Layer           │
├─────────────────────────────────────┤
│         Hibernate API              │
│  (Session, SessionFactory, Query)   │
├─────────────────────────────────────┤
│       Hibernate Core               │
│   (ORM Engine, Caching, Lazy)      │
├─────────────────────────────────────┤
│        JDBC Layer                  │
├─────────────────────────────────────┤
│        Database                    │
└─────────────────────────────────────┘

Integration Patterns

Pattern Purpose Implementation Benefits
DAO Pattern Data access abstraction Repository classes Separation of concerns
Session-per-Request Web application pattern Filter/Interceptor Consistent session lifecycle
Open Session in View Lazy loading in view Web filter Simplifies lazy initialization
Spring Integration Declarative transactions @Transactional Simplified transaction management

16. Spring Integration

Configuration

@Configuration
@EnableTransactionManagement
public class HibernateConfig {
    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan("com.example.model");
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }
}

Repository Pattern

@Repository
@Transactional
public class EmployeeDAO {
    @Autowired
    private SessionFactory sessionFactory;
    
    public void save(Employee emp) {
        sessionFactory.getCurrentSession().save(emp);
    }
}

Quick Reference & Best Practices

Essential Session Methods

Method Purpose Returns Use Case
save(entity) Insert new record Serializable ID New transient entities
persist(entity) Make persistent void JPA-compliant persistence
update(entity) Update detached void Known detached entities
merge(entity) Copy to persistent Merged entity Safe detached updates
saveOrUpdate(entity) Insert or update Serializable ID Unknown entity state
delete(entity) Mark for deletion void Entity removal
get(Class, ID) Load immediately Entity or null When null is acceptable
load(Class, ID) Load lazily Proxy When entity must exist
flush() Force synchronization void Manual sync to DB
clear() Clear session cache void Memory management
evict(entity) Remove from cache void Selective cache clearing
refresh(entity) Reload from DB void Sync with latest DB state

HQL Quick Reference

Category Keywords Example
Basic SELECT, FROM, WHERE FROM Employee WHERE salary > 50000
Joins JOIN, LEFT JOIN, RIGHT JOIN FROM Employee e JOIN e.department d
Aggregation COUNT, SUM, AVG, MAX, MIN SELECT COUNT(e) FROM Employee e
Grouping GROUP BY, HAVING SELECT d.name, COUNT(e) FROM Employee e JOIN e.department d GROUP BY d.name
Ordering ORDER BY, ASC, DESC FROM Employee ORDER BY salary DESC
Conditions IN, NOT IN, BETWEEN, LIKE WHERE e.department IN ('IT', 'HR')
Null Checks IS NULL, IS NOT NULL WHERE e.manager IS NOT NULL
Logic AND, OR, NOT WHERE e.active = true AND e.salary > 40000

Performance Best Practices

✅ Session Management

  • Keep sessions short-lived (per request/transaction)
  • Always close sessions in finally blocks
  • Use one session per thread/request
  • Avoid session sharing across threads

✅ Query Optimization

  • Use lazy loading by default (FetchType.LAZY)
  • Apply JOIN FETCH for known eager requirements
  • Implement pagination for large result sets
  • Use projections to select only needed columns
  • Leverage batch fetching with @BatchSize

✅ Caching Strategy

  • Enable first-level cache (automatic)
  • Configure second-level cache for read-heavy entities
  • Use query cache for repeated queries
  • Set appropriate cache regions and strategies

✅ Transaction Management

  • Use proper transaction boundaries
  • Handle exceptions with rollback
  • Keep transactions short
  • Use optimistic locking for concurrent access

✅ Bulk Operations

  • Use batch processing for large datasets
  • Call flush() and clear() periodically
  • Use bulk update/delete HQL for mass operations
  • Configure batch size in hibernate properties

Configuration Essentials

# Connection settings
hibernate.connection.driver_class=com.mysql.cj.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/mydb
hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

# Performance settings
hibernate.jdbc.batch_size=25
hibernate.order_inserts=true
hibernate.order_updates=true
hibernate.jdbc.batch_versioned_data=true

# Cache settings
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

# Development settings
hibernate.show_sql=false
hibernate.format_sql=true
hibernate.hbm2ddl.auto=validate

Common Pitfalls & Solutions

Pitfall Problem Solution
N+1 Query Problem One query + N additional queries Use JOIN FETCH or @BatchSize
LazyInitializationException Accessing lazy prop after session close Initialize in session or use Open Session in View
Memory Leaks Large sessions not cleared Call clear() periodically in batch operations
Non-unique Object Same entity in session twice Use merge() instead of update()
Dirty Checking Overhead Too many tracked entities Use stateless session for read-only operations
Wrong Cascade Unintended operations Be specific about cascade types

Troubleshooting Checklist

  • Check SQL logs: Enable show_sql and format_sql
  • Verify entity mappings: Ensure correct annotations and relationships
  • Monitor session lifecycle: Check proper opening/closing
  • Review transaction boundaries: Ensure proper transaction management
  • Analyze query patterns: Look for N+1 problems and unnecessary queries
  • Check cache configuration: Verify cache regions and strategies
  • Validate database schema: Ensure entity mappings match database structure
  • Review lazy loading: Check for LazyInitializationExceptions

Production Deployment Checklist

  • Disable SQL logging: Set show_sql=false in production
  • Configure connection pooling: Use HikariCP or similar
  • Set up monitoring: Track query performance and cache hit rates
  • Enable statistics: Configure Hibernate statistics collection
  • Optimize cache: Fine-tune cache regions and eviction policies
  • Set appropriate timeouts: Configure query and connection timeouts
  • Use validation mode: Set hbm2ddl.auto=validate for production
  • Configure batch sizes: Optimize batch processing parameters

Integration with Spring Boot

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=user
spring.datasource.password=password

spring.jpa.hibernate.ddl-auto=validate
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.jdbc.batch_size=25
spring.jpa.properties.hibernate.order_inserts=true

Memory Management Tips

// For batch processing
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for (int i = 0; i < 100000; i++) {
    Employee emp = new Employee("Name" + i);
    session.save(emp);
    
    if (i % 50 == 0) { // Batch size
        session.flush();    // Execute SQL
        session.clear();    // Clear persistence context
    }
}

tx.commit();
session.close();

Testing Best Practices

// Use H2 in-memory database for tests
@TestPropertySource(properties = {
    "spring.datasource.url=jdbc:h2:mem:testdb",
    "spring.jpa.hibernate.ddl-auto=create-drop"
})
@DataJpaTest
class EmployeeRepositoryTest {
    
    @Autowired
    private TestEntityManager entityManager;
    
    @Test
    void testFindByDepartment() {
        // Test implementation
        entityManager.flush(); // Force SQL execution
        entityManager.clear(); // Clear persistence context
    }
}
Found this useful? Pass it on.
Pro · $10/mo

The sheet is free. Pro goes deeper.

Pro opens the full question library behind every sheet, every refresher and a monthly AI allowance. One subscription, all formats.

Full question library All refreshers Cancel anytime