Hibernate Interview Questions
1. What is Hibernate, and how does it differ from JDBC? What are its advantages?
Hibernate is an Object-Relational Mapping (ORM) framework for Java. It helps developers map Java classes to database tables and Java data types to SQL data types, allowing you to interact with databases using standard Java objects rather than SQL queries.
Difference between Hibernate and JDBC
Aspect | JDBC | Hibernate |
---|---|---|
Query Type | SQL (manual) | HQL (object-oriented) |
Mapping | Manual mapping | Automatic ORM mapping |
Code | More boilerplate | Less, cleaner code |
Database Dependency | DB-specific SQL | DB-independent via dialects |
Caching | Not available | Built-in caching support |
Transaction Handling | Manual | Automatic/integrated |
Maintenance | Harder | Easier |
Advantages of Hibernate (Short)
- Reduces boilerplate code
- Automatic object-table mapping
- Database independent (HQL)
- Built-in caching for better performance
- Handles transactions automatically
- Supports lazy loading and relationships
- Easier to maintain and scale
2. What is Object-Relational Mapping (ORM), and how does Hibernate implement it?
Object-Relational Mapping (ORM) is a technique that maps Java objects to database tables and vice versa. It allows developers to interact with the database using Java objects instead of SQL queries.
How does Hibernate implement ORM?
Hibernate uses:
- Annotations (like
@Entity
,@Table
,@Id
,@Column
) or XML files to define the mapping between Java classes and database tables. - Session objects to manage CRUD operations.
- HQL (Hibernate Query Language) to perform database operations using object-oriented syntax.
- Automatic handling of relationships (OneToMany, ManyToOne, etc.), inheritance, and cascading.
3. Describe the architecture of Hibernate. What are the roles of Configuration, SessionFactory, Session, Transaction, and Cache?
Hibernate follows a layered architecture that abstracts interactions between Java applications and databases. It includes various components to handle configuration, session management, transactions, and caching.
Key Components and Their Roles
1. Configuration
- Role: Loads Hibernate configuration details (like DB connection settings and mapping files).
- Use: Usually configured via
hibernate.cfg.xml
or Java-based configuration. - Creates:
SessionFactory
.
2. SessionFactory
- Role: A thread-safe, heavy-weight object used to create
Session
objects. - Lifecycle: Created once per application; reused across sessions.
- Contains: Metadata and connection pool.
3. Session
- Role: Main interface for performing CRUD operations on persistent objects.
- Not Thread-safe: Should be used for a single unit of work.
- Handles: Object-level caching (first-level cache).
4. Transaction
- Role: Manages atomicity and consistency during database operations.
- Use: Ensures commit or rollback of changes as a single unit of work.
5. Cache
- First-Level Cache: Enabled by default at the
Session
level. - Second-Level Cache: Optional, configured separately; shared across sessions to reduce DB hits.
- Query Cache: Optional cache to store query results.
Flow of Hibernate Architecture
- Configuration loads DB and mapping settings.
- SessionFactory is created from Configuration.
- Session is opened from SessionFactory.
- Transaction is started via Session.
- Perform CRUD operations.
- Commit or rollback Transaction.
- Close the Session.
4. Explain the life cycle of a Hibernate entity. What is the difference between Transient, Persistent, and Detached states?
An entity in Hibernate goes through three main states during its life cycle:
1. Transient State
- Meaning: The object is created using
new
, but not associated with any HibernateSession
. - Not saved to the database.
- No primary key (ID is not generated).
- Example:
Student s = new Student(); // Transient state
2. Persistent State
- Meaning: The object is associated with an active Session and will be tracked by Hibernate.
- Any changes to the object will be automatically synchronized with the database during flush/commit.
- Example:
session.save(s); // Now in Persistent state
3. Detached State
- Meaning: The object was once persistent (attached to a session), but now the session is closed.
- It is not being tracked by Hibernate anymore.
- You can reattach it using
session.update()
orsession.merge()
. - Example:
session.close(); // s becomes Detached
State Comparison Table
State | Associated with Session? | Stored in DB? | Changes tracked? |
---|---|---|---|
Transient | β No | β No | β No |
Persistent | β Yes | β Yes | β Yes |
Detached | β No | β Yes | β No |
5. What are the differences between Session
and SessionFactory
? Are they thread-safe?
In Hibernate, SessionFactory
is a heavyweight, thread-safe object that is used to create Session
instances. It is created once during the application startup and is meant to be reused throughout the application’s lifetime. SessionFactory
is responsible for reading the Hibernate configuration (like database connection details and entity mappings) and holds the metadata of persistent classes. It also optionally manages the second-level cache to optimize performance.
In contrast, a Session
is a lightweight, non-thread-safe object that represents a single unit of work with the database. It is created by the SessionFactory
and is used to perform CRUD operations like saving, updating, deleting, or retrieving Java objects from the database. Each session has its own first-level cache, which helps reduce database hits within the scope of that session.
The key difference lies in their usage and lifecycle. While SessionFactory
is shared globally and reused across threads, a Session
is short-lived and should be used per request or transaction. You should never share a Session
between multiple threads as it may lead to concurrency issues.
6. What is the difference between get()
and load()
methods in Hibernate?
Hibernate provides two methods to fetch data from the database: get()
and load()
. Both are used to retrieve an entity by its primary key, but they behave differently.
1. get()
Method:
- Immediate Fetching: Hits the database immediately and returns the actual object.
- Returns:
null
if the object is not found. - Use Case: When you are unsure whether the object exists and want to check.
Example:
Student s = session.get(Student.class, 1);
2. load()
Method:
- Lazy Loading: Returns a proxy object without hitting the database immediately.
- Throws Exception: If the object doesnβt exist, it throws
ObjectNotFoundException
when accessed. - Use Case: When you are sure the object exists and want to improve performance using lazy fetch.
Example:
Student s = session.load(Student.class, 1);
Feature | get() | load() |
---|---|---|
Fetching Type | Eager (immediate) | Lazy (proxy) |
Return if Missing | Returns null | Throws ObjectNotFoundException |
Proxy Object | No | Yes |
When to Use | When object may not exist | When you’re sure object exists |
7. Compare save()
, persist()
, and saveOrUpdate()
in terms of behavior and entity state management.
save()
The save()
method is used to store a new object (like a student or employee) into the database. It returns the generated ID of that object. It can also save an object even if it was saved before in another session (detached state).
Example:
Student student = new Student();
student.setName("Rahul");
Serializable id = session.save(student); // saves the student and returns the ID
System.out.println("Saved with ID: " + id);
- Works with new and detached objects
- Returns the ID (e.g., 101)
- Saves immediately or on flush
- Does not need cascade settings
persist()
The persist()
method is almost like save()
, but it does not return the ID. It follows JPA standards and does not work with detached objects. You must use it only for new objects. Also, it will save the data only when the session is flushed or the transaction is committed.
Example:
Student student = new Student();
student.setName("Rahul");
session.persist(student); // saves the student but returns nothing
- Works only with new objects
- Doesnβt return ID
- Inserts during flush/commit
- Needs
CascadeType.PERSIST
to save child objects
saveOrUpdate()
The saveOrUpdate()
method is smart. It checks whether the object is new or already exists. If itβs new, it will insert it. If it already exists in the database (has an ID), it will update it. It works for both new and detached objects.
Example:
Student student = new Student();
student.setId(101); // already exists
student.setName("Updated Name");
session.saveOrUpdate(student); // will update if exists, save if not
- Works with both new and old objects
- No ID return
- Automatically decides insert or update
- Useful when youβre not sure if the object is new or existing
8. How is transaction management handled in Hibernate using Session.beginTransaction()
, commit()
, and rollback()
?
In Hibernate, a transaction ensures that a set of database operations are executed in a safe, consistent, and atomic way β meaning either all operations succeed, or none do. This helps prevent issues like partial updates or data corruption. Hibernate handles transactions using the Transaction
API along with the Session
object.
Key Methods:
beginTransaction()
- Starts a new database transaction.
- Called on the
Session
object.
commit()
- Finalizes the transaction.
- Applies all changes made during the transaction to the database.
rollback()
- Cancels the transaction.
- Reverts all changes if any error occurs.
Example
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Student s = new Student();
s.setName("Rahul");
session.save(s); // Save operation inside the transaction
tx.commit(); // Commit if everything is successful
} catch (Exception e) {
if (tx != null) tx.rollback(); // Rollback on error
e.printStackTrace();
} finally {
session.close();
}
What Happens in the Above Code?
- A new session is opened.
- A transaction is started using
beginTransaction()
. - The student object is saved.
- If all goes well,
commit()
saves changes to the database. - If something fails (like an exception),
rollback()
undoes all changes. - The session is closed at the end.
9. What is the difference between HQL (Hibernate Query Language) and SQL? What are the advantages of using HQL?
Aspect | SQL (Structured Query Language) | HQL (Hibernate Query Language) |
---|---|---|
Works On | Tables and columns directly | Java classes and their properties (objects) |
Return Type | Returns rows and columns (ResultSet) | Returns Java objects/entities |
Database Dependent? | Yes (DB-specific syntax may vary) | No (DB-independent; Hibernate converts to SQL) |
Query Style | Table-oriented | Object-oriented |
Joins | Manual joins using table names | Uses object relationships (like mapped associations) |
Use in Hibernate | Can be used but not recommended | Preferred in Hibernate for object manipulation |
Advantages of HQL (Hibernate Query Language)
- Object-Oriented: Uses Java class and property names instead of table/column names.
- Database Independent: Works across different databases using Hibernate dialects.
- Returns Objects: Fetches Java entities instead of raw data.
- Supports Relationships: Easily queries mapped associations like OneToMany.
- Cleaner Code: Reduces SQL errors and aligns better with Java code.
10. How does the Criteria API differ from HQL? When would you use each for dynamic queries?
HQL (Hibernate Query Language) is a string-based, object-oriented query language that looks similar to SQL but works with Java class names and fields instead of table and column names. It’s very useful when your queries are staticβmeaning the structure doesn’t change at runtime. For example, if you want to get all students named “Rahul”, you can simply write:
String hql = "FROM Student WHERE name = :name";
Query query = session.createQuery(hql);
query.setParameter("name", "Rahul");
List<Student> list = query.list();
This is clean, readable, and easy to maintain if the query is fixed.
Criteria API is useful when you need to build dynamic queries. Instead of using strings, you use Java methods to build the query step by step. This is especially helpful when the query changes based on user inputβlike applying different filters based on a search form. For example:
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Student> cq = cb.createQuery(Student.class);
Root<Student> root = cq.from(Student.class);
List<Predicate> predicates = new ArrayList<>();
if (nameFilter != null) {
predicates.add(cb.equal(root.get("name"), nameFilter));
}
if (ageFilter != null) {
predicates.add(cb.equal(root.get("age"), ageFilter));
}
cq.select(root).where(cb.and(predicates.toArray(new Predicate[0])));
List<Student> result = session.createQuery(cq).getResultList();
Here, you can easily add or remove conditions without rewriting the whole query, making it perfect for advanced search, admin dashboards, or filter panels.
In summary, use HQL for simple, fixed queries and use the Criteria API when you need flexible, dynamic queries that change at runtime.
11. What is Hibernate caching? What is the difference between first-level and second-level caching?
Hibernate caching is a performance optimization technique that reduces the number of database queries by storing frequently accessed data in memory. Instead of hitting the database every time you fetch an entity, Hibernate can return data from its internal cache if it was previously loaded.
Caching helps improve speed, reduce database load, and make applications more efficient.
Types of Caching in Hibernate
1. First-Level Cache (Session Cache)
- Enabled by default
- Works at the Session level
- Data is cached per session (only available within the same session)
- When you fetch the same entity twice in the same session, the second fetch is served from memory
Session session = sessionFactory.openSession();
Student s1 = session.get(Student.class, 1); // Hits DB
Student s2 = session.get(Student.class, 1); // Comes from cache
2. Second-Level Cache
- Optional β must be enabled and configured explicitly
- Works at the SessionFactory level
- Shared across multiple sessions
- Useful for caching data that doesnβt change often and is accessed frequently
// First time (from DB, stored in second-level cache)
Session s1 = sessionFactory.openSession();
Student student = s1.get(Student.class, 1);
s1.close();
// Second time (new session, from cache if enabled)
Session s2 = sessionFactory.openSession();
Student sameStudent = s2.get(Student.class, 1);
s2.close();
12. What are the benefits of using second-level cache, and how do you enable it?
Benefits of Using Second-Level Cache in Hibernate
- Improves Performance
- Reduces repeated database queries for frequently accessed data.
- Shared Across Sessions
- Unlike first-level cache, second-level cache is shared across multiple sessions and users.
- Reduces Database Load
- Less traffic to the database means better scalability and responsiveness.
- Faster Access to Read-Only or Rarely Changing Data
- Ideal for caching reference or lookup data like categories, states, roles, etc.
- Customizable
- You can choose what entities or collections to cache and for how long.
How to Enable Second-Level Cache in Hibernate
1. Add a Cache Provider Dependency (e.g., EHCache, Infinispan) For EHCache, add to pom.xml
:
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>YOUR_HIBERNATE_VERSION</version>
</dependency>
2. Update hibernate.cfg.xml
or application.properties
:
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
3. Enable Caching on Entity Class Using Annotation:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Product {
@Id
private Long id;
private String name;
}
4. Add ehcache.xml
Configuration File (if using EHCache)
<ehcache>
<defaultCache
maxEntriesLocalHeap="1000"
timeToLiveSeconds="300"
eternal="false"
overflowToDisk="false"/>
</ehcache>
When to Use Second-Level Cache
- For read-mostly entities
- For reference data that rarely changes
- When you need to reduce DB load in a high-traffic application
13. What is JDBC batching in Hibernate, and how is it configured using hibernate.jdbc.batch_size
?
JDBC batching is a performance optimization technique where multiple SQL statements are grouped together and sent to the database in a single batch instead of one by one. This reduces the number of database round-trips, improving the performance of bulk insert, update, or delete operations.
Hibernate supports JDBC batching out of the box, and it can be especially useful when you’re saving or updating multiple records in a loop.
How to Enable JDBC Batching in Hibernate
You can enable batching by setting the property hibernate.jdbc.batch_size
in your configuration:
In hibernate.cfg.xml:
<property name="hibernate.jdbc.batch_size">20</property>
In application.properties (Spring Boot):
hibernate.jdbc.batch_size=20
14. What are the differences between eager and lazy fetching in Hibernate?
- Lazy = Load only when needed β better performance
- Eager = Load everything upfront β may waste resources
1. Lazy Fetching (FetchType.LAZY
)
- Default behavior for most relationships (like
@OneToMany
,@ManyToMany
) - Related data is not loaded immediately
- Data is fetched only when accessed (on-demand)
- Improves performance by avoiding unnecessary data loading
Example:
@Entity
public class Student {
@OneToMany(fetch = FetchType.LAZY)
private List<Course> courses;
}
Courses wonβt be fetched when you load the student. They will be fetched only when student.getCourses()
is called.
2. Eager Fetching (FetchType.EAGER
)
- Related data is loaded immediately with the main entity
- Fetches all associations at once, even if not needed
- Can cause performance issues due to unnecessary data loading (especially in collections)
Example:
@Entity
public class Student {
@OneToMany(fetch = FetchType.EAGER)
private List<Course> courses;
}
Courses will be loaded as soon as the student is fetched.
15. How can you handle the N+1 select problem in Hibernate?
N+1 select problem
- You fetch a list of entities (1 query), and
- For each entity, Hibernate issues another query to load associated data (N queries),
- So total N + 1 queries are executed instead of just 1 optimized query with a join.
Example Problem:
List<Student> students = session.createQuery("FROM Student").list();
for (Student s : students) {
System.out.println(s.getCourses().size()); // Triggers separate query for each student
}
If there are 100 students, youβll end up with 101 queries!
Solutions to the N+1 Select Problem
1. Use JOIN FETCH in HQL
Tell Hibernate to fetch associated entities using a single join query.
List<Student> students = session.createQuery(
"SELECT s FROM Student s JOIN FETCH s.courses", Student.class
).list();
Result: Only one query is executed with an inner join.
2. Use @BatchSize Annotation
Fetch multiple lazy-loaded associations in batches rather than one-by-one.
@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
@BatchSize(size = 10)
private List<Course> courses;
Result: Reduces total queries (e.g., from 100 to 10).
3. Use EntityGraph (JPA 2.1+)
Specify what to fetch eagerly using a graph, without changing your entity mapping.
EntityGraph<?> graph = em.createEntityGraph("student-with-courses");
TypedQuery<Student> query = em.createQuery("SELECT s FROM Student s", Student.class);
query.setHint("javax.persistence.fetchgraph", graph);
JPA Interview Questions
1. What is JPA (Java Persistence API), and what is its main purpose in a Java application?
JPA (Java Persistence API) is a Java specification that defines a standard way to manage relational data in Java applications. It allows developers to map Java objects (entities) to database tables and perform operations like insert, update, delete, and fetch without writing direct SQL queries.
JPA acts as a bridge between Java code and the database by using annotations or XML to define how classes are stored in the database. It simplifies persistence logic by allowing developers to work with objects instead of JDBC code.
Main Purpose of JPA:
- To map Java objects to relational database tables (ORM β Object-Relational Mapping)
- To provide an abstraction layer over JDBC, reducing boilerplate code
- To standardize data access across different frameworks like Hibernate, EclipseLink, etc.
- To make data persistence simple, clean, and maintainable in enterprise applications
2. How does JPA differ from traditional ORM tools and JDBC?
JPA (Java Persistence API) is a high-level specification for object-relational mapping (ORM) in Java, which abstracts and simplifies the process of storing, retrieving, and managing data from relational databases. In contrast, JDBC (Java Database Connectivity) is a low-level API that requires developers to write detailed SQL queries and manage database connections, statements, and result sets manually. This makes JDBC more verbose and error-prone, whereas JPA allows developers to interact with the database using Java objects and annotations, reducing boilerplate code and improving maintainability.
When compared to traditional ORM tools like Hibernate, JPA serves as a standard interface, while Hibernate is an implementation of that interface. JPA provides a consistent programming model that can work across different ORM providers, whereas Hibernate includes additional features beyond the JPA specification, such as advanced caching, custom query language (HQL), and more tuning options. In short, JPA offers portability and simplicity, while tools like Hibernate provide more power and flexibility but may be tied to specific implementations.
3. What is the difference between JPA and Hibernate? How does JPA act as a specification and Hibernate as its implementation?
JPA is the interface (what to do), and Hibernate is the working engine (how to do it). You use JPA annotations and code, but Hibernate runs underneath and handles the actual database operations.
What JPA Provides
- JPA gives you standard annotations like
@Entity
,@Id
,@OneToMany
, etc. - It also provides standard interfaces like
EntityManager
,Query
, andEntityTransaction
. - These are just rules and APIs β they donβt contain any working logic.
What Hibernate Does
- Hibernate is a JPA implementation that takes your JPA code and does the real work behind the scenes.
- When you call
entityManager.persist(student)
, Hibernate is the one actually generating the SQL and executing it. - If you switch to another JPA provider like EclipseLink, it will follow the same JPA rules but use its own engine.
4. What is an @Entity
in JPA? How is an entity class mapped to a database table?
In JPA, @Entity
is an annotation used to tell the framework that a Java class should be mapped to a table in the database. When you mark a class with @Entity
, JPA treats it as a persistent entity, meaning its objects can be stored, retrieved, and managed by the database through JPA.
How is an Entity Class Mapped to a Database Table?
When you annotate a class with @Entity
, JPA will by default:
- Use the class name as the table name
- Use fields as columns
- Use the field marked with
@Id
as the primary key
You can customize this mapping using annotations like @Table
, @Column
, and @GeneratedValue
.
5. What are the different primary key generation strategies in JPA? Explain AUTO
, IDENTITY
, SEQUENCE
, and TABLE
.
In JPA, the @GeneratedValue
annotation is used to automatically generate primary key values, and it supports 4 strategies:
@GeneratedValue(strategy = GenerationType.STRATEGY_NAME)
1. AUTO
- Default strategy β JPA chooses the best strategy based on the database.
- It may choose
IDENTITY
,SEQUENCE
, orTABLE
internally. - Suitable when you want to let JPA decide.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
Use when: You want to write DB-independent code.
2. IDENTITY
- Relies on auto-increment columns (supported by MySQL, SQL Server, etc.).
- The database generates the ID during the
INSERT
.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Use when: You are using databases like MySQL or SQL Server that support auto-increment fields.
3. SEQUENCE
- Uses a database sequence object to generate IDs.
- Supported by databases like PostgreSQL, Oracle, etc.
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "student_seq")
@SequenceGenerator(name = "student_seq", sequenceName = "student_sequence", allocationSize = 1)
private Long id;
Use when: Your database supports sequences and you want more control.
4. TABLE
- Uses a separate table to store and generate primary key values.
- Works on any database, but is slower and less efficient.
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "student_tbl")
@TableGenerator(name = "student_tbl", table = "id_generator", pkColumnName = "key_name", valueColumnName = "next_id", pkColumnValue = "student_id", allocationSize = 1)
private Long id;
Use when: You want full database independence, but itβs rarely used due to performance.
6. What are basic CRUD operations in JPA? How can you perform Create, Read, Update, and Delete using EntityManager
?
CRUD stands for:
- C β Create (insert new records)
- R β Read (fetch data)
- U β Update (modify existing records)
- D β Delete (remove records)
In JPA, these operations are performed using the EntityManager
interface.
1. Create (Insert)
To insert a new entity into the database, use persist()
:
Student student = new Student();
student.setName("Rahul");
student.setAge(22);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(student); // Adds new record
em.getTransaction().commit();
em.close();
2. Read (Find/Retrieve)
To fetch a record by its primary key, use find()
:
EntityManager em = emf.createEntityManager();
Student student = em.find(Student.class, 1L); // Retrieves student with ID 1
em.close();
You can also use JPQL:
List<Student> list = em.createQuery("SELECT s FROM Student s", Student.class).getResultList();
3. Update
To update an entity, use merge()
:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Student student = em.find(Student.class, 1L);
student.setAge(25); // Change value
em.merge(student); // Optional here, as the object is managed
em.getTransaction().commit();
em.close();
If the object is already managed (like after
find()
), you can skipmerge()
and just modify the object.
4. Delete
To delete an entity, use remove()
:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Student student = em.find(Student.class, 1L);
em.remove(student); // Deletes the record
em.getTransaction().commit();
em.close();
7. What are the different entity states in JPA? Explain Transient, Managed, Detached, and Removed states.
State | Description |
---|---|
Transient | Entity is not associated with any EntityManager , and not stored in DB |
Managed | Entity is in persistence context, tracked by EntityManager (synced to DB) |
Detached | Entity was managed, but now it’s disconnected from EntityManager |
Removed | Entity is marked for deletion, and will be deleted when transaction commits |
1. Transient State
- Object is created using
new
, but not yet persisted - No DB row exists, and no tracking by JPA
Student s = new Student(); // Transient
s.setName("Amit");
2. Managed (Persistent) State
- Entity is now being tracked by JPA
- Changes to the object will be automatically synchronized with the database
- Occurs after calling
persist()
orfind()
em.persist(s); // Now it's managed
3. Detached State
- Entity was managed but is now disconnected (e.g., after
em.close()
or after transaction ends) - Changes are not saved unless reattached (via
merge()
)
em.close(); // or after commit
s.setName("Updated"); // Not tracked anymore
4. Removed State
- Entity is marked for deletion using
em.remove()
- Actual deletion occurs after transaction commit
em.remove(s); // s is now in removed state
Life Cycle Summary (Easy Flow):
new Student() --> Transient
em.persist(student) --> Managed
em.detach(student) --> Detached
em.remove(student) --> Removed
8. What are cascade types in JPA? Describe the use of ALL
, PERSIST
, MERGE
, REMOVE
, REFRESH
, and DETACH
.
Cascade types tell JPA which operations should be applied to the associated child entities when an operation is performed on the parent.
In simple words we can say, Cascade tells JPA: “If you do something to the parent, should I do the same to the child?”
For example, if you save or delete a Student
, should JPA also save or delete the Courses
linked to that student?
Cascade types are set using the cascade
attribute:
@OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
private List<Course> courses;
Cascade Type | Description |
---|---|
ALL | Applies all cascade operations |
PERSIST | Saves child when parent is saved |
MERGE | Updates child when parent is updated |
REMOVE | Deletes child when parent is deleted |
REFRESH | Reloads child when parent is refreshed |
DETACH | Detaches child when parent is detached |
9. How are relationships managed in JPA? Explain with examples: @OneToOne
, @OneToMany
, @ManyToOne
, and @ManyToMany
.
JPA handles relationships using annotations like @OneToOne
, @OneToMany
, @ManyToOne
, and @ManyToMany
.
1. @OneToOne
β One entity is related to exactly one other entity
Example: A Person
has one Passport
.
@Entity
public class Person {
@Id
private Long id;
@OneToOne
private Passport passport;
}
@Entity
public class Passport {
@Id
private Long id;
private String passportNumber;
}
Bidirectional mapping can be done using
mappedBy
.
2. @OneToMany
β One entity is related to many of another entity
Example: A Customer
can have many Orders
.
@Entity
public class Customer {
@Id
private Long id;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
private List<Order> orders;
}
@Entity
public class Order {
@Id
private Long id;
@ManyToOne
private Customer customer;
}
Typically used with
@ManyToOne
on the child side to manage the relationship.
3. @ManyToOne
β Many entities are related to one entity
Example: Many Orders
belong to one Customer
.
@Entity
public class Order {
@Id
private Long id;
@ManyToOne
private Customer customer;
}
This is the owning side in most relationships.
4. @ManyToMany
β Many entities are related to many others
Example: A Student
can enroll in many Courses
, and a Course
can have many Students
.
@Entity
public class Student {
@Id
private Long id;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private List<Course> courses;
}
@Entity
public class Course {
@Id
private Long id;
@ManyToMany(mappedBy = "courses")
private List<Student> students;
}
Creates a join table to manage many-to-many mapping.
10. How do you implement pagination in JPA using setFirstResult()
and setMaxResults()
?
JPA provides two methods on the Query
or TypedQuery
object for pagination:
setFirstResult(int startPosition)
β Starting row (zero-based)setMaxResults(int maxResult)
β Number of records to fetch (page size)
Example:
Letβs say you want to fetch page 2 with 5 records per page (i.e., records 6β10):
int pageNumber = 2;
int pageSize = 5;
EntityManager em = emf.createEntityManager();
TypedQuery<Student> query = em.createQuery("SELECT s FROM Student s", Student.class);
query.setFirstResult((pageNumber - 1) * pageSize); // (2 - 1) * 5 = 5
query.setMaxResults(pageSize); // 5 results
List<Student> students = query.getResultList();
11. What is the role of @Version
in JPA?
@Version
in JPA is used to implement optimistic locking, which helps prevent conflicts when multiple users try to update the same database record at the same time.
Key Points:
- It marks a field (like
int
,long
, orTimestamp
) as the version field of the entity. - JPA uses this field to track the version of each record in the database.
- During an update, JPA includes the version in the SQL
WHERE
clause. - If the version doesnβt match (i.e., another user has updated it), JPA throws an
OptimisticLockException
and the update is rejected.