Interview Prep
Interview Questions on Hibernate — ORM, Session Lifecycle, Caching, N+1 Problem & HQL
Hibernate is the default ORM for Java in India. Every Spring Boot project uses Hibernate/JPA under the hood. If you are interviewing for any Java backend role — service company or product company — Hibernate questions are guaranteed. Here are the 10 questions that actually get asked.

Hibernate powers nearly every Java backend in India. From TCS to Flipkart, ORM knowledge is non-negotiable.
Hibernate in Indian IT Interviews
Hibernate is the default ORM for Java in India. Every Spring Boot project uses Hibernate/JPA. Whether you are building microservices at a product company or maintaining enterprise applications at a service company, Hibernate is the data access layer. It is tested in every Java backend interview — from fresher rounds to architect-level discussions.
Interviewers test three areas: ORM fundamentals (what Hibernate does and why), session and caching mechanics (how it works internally), and performance optimization (how to use it without killing your database). Freshers get annotation and mapping questions. Experienced candidates get N+1 problems, caching strategies, and batch processing scenarios.
This guide covers the 10 Hibernate questions that actually appear in Indian interviews — with code examples and architecture explanations.
“What is the difference between Hibernate and JPA?” — this is the opening question in almost every Java backend interview. Get it wrong and the interviewer assumes you have only copy-pasted annotations.
ORM Basics
Q1: What is Hibernate? How is it different from JDBC?
Hibernate is an ORM (Object-Relational Mapping) framework that maps Java objects to database tables. Instead of writing raw SQL and manually mapping ResultSets to objects, Hibernate handles the translation automatically.
Hibernate vs JDBC — Comparison:
JDBC (Manual): Hibernate (ORM):
───────────────────────────── ─────────────────────────────
Write SQL manually Object-oriented queries (HQL)
Manual ResultSet → Object Automatic mapping (@Entity)
No caching First-level + second-level cache
Manual connection management Built-in connection pooling
Manual transaction handling Declarative transactions
No lazy loading Lazy loading by default
Database-specific SQL Database-independent (dialect)
// JDBC approach:
String sql = "SELECT * FROM employees WHERE id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 101);
ResultSet rs = ps.executeQuery();
Employee emp = new Employee();
emp.setId(rs.getInt("id"));
emp.setName(rs.getString("name"));
// Hibernate approach:
Employee emp = session.get(Employee.class, 101);
// That's it. One line.Q2: What is the difference between Hibernate and JPA?
JPA = specification (interface/contract)
Hibernate = implementation (actual code)
JPA defines the standard annotations:
@Entity, @Table, @Id, @Column,
@OneToMany, @ManyToOne, etc.
Hibernate implements those annotations.
Other JPA implementations:
- EclipseLink (reference implementation)
- OpenJPA (Apache)
- TopLink (Oracle)
In practice:
- Everyone uses JPA annotations
- Hibernate is the runtime underneath
- Spring Boot auto-configures Hibernate as JPA provider
// You write JPA code:
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "full_name")
private String name;
}
// Hibernate executes it behind the scenes.
// This is why you see "Hibernate" in logs
// but use "javax.persistence" annotations.Session & Caching
Q3: Explain the Hibernate Session lifecycle. What are the object states?
Hibernate Object States:
Transient → Persistent → Detached → Removed
1. TRANSIENT: new object, not in DB, not tracked
Employee emp = new Employee(); // transient
emp.setName("Rahul");
2. PERSISTENT: associated with session, tracked by Hibernate
session.save(emp); // now persistent
// Any changes to emp are auto-synced to DB
emp.setName("Rahul Kumar"); // auto-updated!
3. DETACHED: was persistent, session is closed
session.close(); // emp is now detached
emp.setName("New Name"); // NOT tracked anymore
// To re-attach:
session.update(emp); // or session.merge(emp)
4. REMOVED: marked for deletion
session.delete(emp); // marked for removal
// Deleted from DB on flush/commit
State transitions:
new Object() → Transient
session.save() → Persistent
session.close() → Detached
session.delete() → Removed
session.merge() → Detached → Persistent
session.update() → Detached → PersistentQ4: What is the difference between get() and load()?
get() vs load(): get(): - Hits database IMMEDIATELY - Returns null if not found - Returns the actual object - Use when you NEED the object now Employee emp = session.get(Employee.class, 101); // SQL fires immediately // emp is null if ID 101 doesn't exist load(): - Returns a PROXY (no DB hit yet) - Hits DB only when you access a property - Throws ObjectNotFoundException if not found - Use when you just need a reference (FK assignment) Employee emp = session.load(Employee.class, 101); // No SQL yet — emp is a proxy emp.getName(); // NOW SQL fires (lazy loading) When to use load(): // Assigning a foreign key without loading the object Department dept = session.load(Department.class, 5); employee.setDepartment(dept); // No need to load the full Department object // Just need the reference for the FK
Q5: Explain Hibernate caching levels.
Hibernate Caching Architecture:
┌─────────────────────────────────────────┐
│ Application Layer │
├─────────────────────────────────────────┤
│ First-Level Cache (Session Cache) │
│ - Scope: per Session │
│ - Automatic, cannot be disabled │
│ - Same entity loaded twice = 1 SQL │
│ - Cleared when session closes │
├─────────────────────────────────────────┤
│ Second-Level Cache (SessionFactory) │
│ - Scope: shared across all sessions │
│ - Optional, must be configured │
│ - Providers: EhCache, Redis, Hazelcast │
│ - Great for read-heavy, rarely-changed │
│ - @Cacheable on entity class │
├─────────────────────────────────────────┤
│ Query Cache │
│ - Caches query RESULTS (not entities) │
│ - Used with second-level cache │
│ - query.setCacheable(true) │
│ - Invalidated when underlying table │
│ is modified │
├─────────────────────────────────────────┤
│ Database │
└─────────────────────────────────────────┘
First-level cache example:
Employee e1 = session.get(Employee.class, 1); // SQL
Employee e2 = session.get(Employee.class, 1); // NO SQL
// e1 == e2 (same object reference)
Second-level cache config:
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Country { ... }
// Country data cached across all sessionsMapping & Relationships
Q6: How do you map relationships in Hibernate?
Relationship Annotations:
// @OneToOne
@Entity
public class Employee {
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address;
}
// @OneToMany / @ManyToOne (most common)
@Entity
public class Department {
@OneToMany(mappedBy = "department",
cascade = CascadeType.ALL)
private List<Employee> employees;
}
@Entity
public class Employee {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dept_id")
private Department department;
}
// @ManyToMany
@Entity
public class Student {
@ManyToMany
@JoinTable(name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private Set<Course> courses;
}
// Bidirectional: use mappedBy on the non-owning side
// Cascade types: ALL, PERSIST, MERGE, REMOVE,
// REFRESH, DETACH
// FetchType: LAZY (default for collections),
// EAGER (default for @ManyToOne)Q7: What is the N+1 problem? How do you fix it?
The N+1 Problem:
1 query for parent + N queries for each child = N+1
Example: Fetch 100 orders, each triggers a query
for its customer:
// BAD: N+1 problem
List<Order> orders = session.createQuery(
"FROM Order").list();
// 1 SQL: SELECT * FROM orders (100 rows)
for (Order o : orders) {
o.getCustomer().getName();
// 100 SQLs: SELECT * FROM customers WHERE id = ?
}
// Total: 101 queries!
Fix 1: JOIN FETCH in HQL
List<Order> orders = session.createQuery(
"FROM Order o JOIN FETCH o.customer").list();
// 1 SQL with JOIN — done!
Fix 2: @BatchSize
@OneToMany
@BatchSize(size = 25)
private List<OrderItem> items;
// Loads 25 children at a time instead of 1
Fix 3: EntityGraph (JPA 2.1)
@EntityGraph(attributePaths = {"customer", "items"})
List<Order> findAll();
// Defines what to fetch eagerly per query
Fix 4: Subselect fetching
@Fetch(FetchMode.SUBSELECT)
private List<OrderItem> items;
// Uses IN (SELECT ...) instead of N queries
Understanding session lifecycle and caching is what separates junior developers from senior Hibernate engineers.
HQL & Performance
Q8: What is HQL? How is it different from SQL?
HQL = Hibernate Query Language
Object-oriented query language that uses
class/property names, NOT table/column names.
HQL vs SQL:
HQL:
FROM Employee e WHERE e.salary > 50000
// Uses class name "Employee", property "salary"
SQL:
SELECT * FROM employees WHERE salary > 50000
// Uses table name "employees", column "salary"
HQL features:
- Polymorphism: FROM Payment → returns all subtypes
- Pagination: query.setFirstResult(0).setMaxResults(10)
- Named parameters: WHERE e.name = :name
- Joins: FROM Employee e JOIN e.department d
- Projections: SELECT e.name, e.salary FROM Employee e
- Aggregates: SELECT AVG(e.salary) FROM Employee e
// Named query (reusable, pre-compiled)
@NamedQuery(
name = "Employee.findByDept",
query = "FROM Employee e WHERE e.department.name = :dept"
)
// Usage:
Query q = session.getNamedQuery("Employee.findByDept");
q.setParameter("dept", "Engineering");
List<Employee> results = q.list();Q9: What is the difference between Criteria API and HQL?
HQL: string-based, like SQL but object-oriented
Criteria: programmatic, type-safe, dynamic queries
HQL — better for static, readable queries:
String hql = "FROM Employee e WHERE e.salary > :min "
+ "AND e.department.name = :dept";
// Clean, readable, easy to understand
Criteria API — better for dynamic filters:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
Root<Employee> root = cq.from(Employee.class);
List<Predicate> predicates = new ArrayList<>();
if (minSalary != null)
predicates.add(cb.gt(root.get("salary"), minSalary));
if (deptName != null)
predicates.add(cb.equal(
root.get("department").get("name"), deptName));
cq.where(predicates.toArray(new Predicate[0]));
// Dynamic — only adds filters that are provided
When to use what:
HQL → fixed queries, reports, simple lookups
Criteria → search forms, dynamic filters, type-safe
Note: Hibernate's old Criteria API (org.hibernate.Criteria)
is DEPRECATED. Use JPA Criteria API (javax.persistence).Q10: How do you optimize Hibernate performance?
Hibernate Performance Optimization Checklist:
1. Batch processing:
hibernate.jdbc.batch_size = 25
// Groups INSERT/UPDATE into batches
for (int i = 0; i < 10000; i++) {
session.save(entities.get(i));
if (i % 25 == 0) {
session.flush();
session.clear(); // prevent memory overflow
}
}
2. Lazy loading by default:
@ManyToOne(fetch = FetchType.LAZY)
// Don't load what you don't need
3. Use projections (select specific columns):
SELECT new EmployeeDTO(e.name, e.salary)
FROM Employee e
// Don't load entire entity for a dropdown
4. Fix N+1 with JOIN FETCH:
FROM Order o JOIN FETCH o.customer
// One query instead of N+1
5. Second-level cache for read-heavy data:
@Cacheable // countries, states, config
// Avoid DB hits for rarely-changed data
6. StatelessSession for bulk operations:
StatelessSession ss = sf.openStatelessSession();
// No cache, no dirty checking, no cascades
// Pure speed for batch imports
7. Monitor with logging:
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.generate_statistics = true
// See exactly what SQL Hibernate generatesHow to Prepare
Hibernate Interview — Priority by Experience
Freshers (0-1 years)
- • ORM basics & annotations
- • Hibernate vs JDBC vs JPA
- • Session object states
- • Basic mappings (@Entity, @Id)
- • Simple HQL queries
Mid-Level (2-4 years)
- • Caching levels (L1, L2)
- • N+1 problem & fixes
- • Relationship mappings
- • HQL vs Criteria API
- • Lazy vs eager loading
Senior (5+ years)
- • Performance tuning
- • Batch processing
- • Multi-tenancy strategies
- • StatelessSession usage
- • Cache invalidation patterns