What is EntityManager and How Does It Differ from Session
EntityManager and Session are two interfaces for working with ORM in Java. EntityManager is the standard JPA interface, while Session is a Hibernate-specific implementation. Und...
Overview
EntityManager and Session are two interfaces for working with ORM in Java. EntityManager is the standard JPA interface, while Session is a Hibernate-specific implementation. Understanding the differences helps you choose the right abstraction.
Junior Level
What is EntityManager
EntityManager is the JPA standard interface for working with entities. It is defined in the JPA specification and works with any JPA provider (Hibernate, EclipseLink, OpenJPA).
Note: in Hibernate 5 / Java EE, the
javax.persistencepackage is used; in Hibernate 6 / Jakarta EE -jakarta.persistence. Examples below usejakarta.
// JPA standard - works with any provider
@PersistenceContext
private EntityManager em;
em.persist(user);
em.merge(user);
em.remove(user);
User found = em.find(User.class, 1L);
What is Session
Session is a Hibernate-specific interface. It provides additional capabilities not available in the standard JPA.
// Hibernate-specific
Session session = entityManager.unwrap(Session.class);
session.save(user);
session.update(user);
session.delete(user);
User found = session.get(User.class, 1L);
Main Difference
| EntityManager | Session | |
|---|---|---|
| Standard | JPA (jakarta.persistence) | Hibernate (org.hibernate) |
| Portability | Any JPA provider | Hibernate only |
| Methods | persist, merge, remove, find | save, update, delete, get |
| Extra features | No | doWork(), replicate(), etc. |
How to Get Session from EntityManager
Session session = entityManager.unwrap(Session.class);
Middle Level
Method Comparison
EntityManager (JPA) Session (Hibernate)
----------------- -----------------
persist() save()
merge() update(), saveOrUpdate()
remove() delete()
find() get()
createQuery() createQuery()
createNativeQuery() createSQLQuery()
flush() flush()
clear() clear()
contains() contains()
detach() evict()
refresh() refresh()
When to Use EntityManager
// For portability between JPA providers
@Repository
public class UserRepository {
@PersistenceContext
private EntityManager em;
public void save(User user) {
em.persist(user); // standard method
}
}
When to Use Session
// For Hibernate-specific features
Session session = entityManager.unwrap(Session.class);
// Direct Connection access
session.doWork(connection -> {
// JDBC operations
PreparedStatement stmt = connection.prepareStatement("...");
});
// Batch operations
session.doReturningWork(connection -> {
// return result
return result;
});
// Native Hibernate capabilities
session.byMultipleIds(User.class)
.multiLoad(ids);
Additional Session Methods
Session session = entityManager.unwrap(Session.class);
// doWork - work with Connection
session.doWork(new Work() {
public void execute(Connection connection) {
// JDBC operations
}
});
// replicate - copy entity
session.replicate(user, ReplicationMode.OVERWRITE);
// getIdentifier - get ID
Serializable id = session.getIdentifier(user);
// isConnected - connection check
boolean connected = session.isConnected();
Senior Level
Internal Implementation
// In Hibernate 5.2+, Session and EntityManager share internal
// implementation. Session implements EntityManager, rather than wrapping it.
EntityManager - interface from JPA specification (jakarta.persistence)
Session - interface from Hibernate (org.hibernate)
When to Use Session
// 1. Native SQL with result return
Session session = entityManager.unwrap(Session.class);
NativeQuery<User> query = session.createNativeQuery(
"SELECT * FROM users WHERE created_at > :date", User.class);
query.setParameter("date", date);
// 2. Multi-load (Hibernate 5.1+)
List<User> users = session.byMultipleIds(User.class)
.enableCheckCache(true)
.multiLoad(List.of(1L, 2L, 3L));
// 3. Scrollable results (for large data)
ScrollableResults<User> results = session.createQuery("FROM User", User.class)
.setFetchSize(100)
.scroll(ScrollMode.FORWARD_ONLY);
// 4. Statistics
Statistics stats = session.getSessionFactory().getStatistics();
When NOT to Use Session
// If Hibernate-specific features not needed
// If provider change is possible
// For standard CRUD operations
// In libraries/frameworks (violates abstraction)
Best Practices
EntityManager by default
unwrap(Session) when Hibernate features needed
Standard methods for portability
Session for batch/native operations
Session for statistics and monitoring
Session when Hibernate features not needed
Mixing without reason
unwrap() in every method (better to extract)
Direct Session usage in libraries
Interview Cheat Sheet
Must know:
- EntityManager - JPA standard (jakarta.persistence), works with any provider
- Session - Hibernate-specific interface, additional capabilities
- Session obtained via entityManager.unwrap(Session.class)
- EntityManager methods: persist, merge, remove, find; Session: save, update, delete, get
- Session provides: doWork() (JDBC), multi-load, scrollable results, statistics
- EntityManager by default, Session when Hibernate features needed
Frequent follow-up questions:
- When to use Session? Native SQL with result return, multi-load, scrollable results, statistics, batch operations
- When NOT to use Session? Standard CRUD, provider change possible, libraries/frameworks
- Why doWork()? Direct access to JDBC Connection for operations JPA doesn’t support
- What changed in Hibernate 5.2+? Session and EntityManager share internal implementation
Red flags (DO NOT say):
- “I always use Session instead of EntityManager” - ties to Hibernate
- “I mix them without reason” - violates JPA abstraction
- “unwrap() in every method” - better to extract into separate component
- “Session in libraries” - violates portability
Related topics:
- [[7. Describe the Entity Lifecycle in Hibernate]]
- [[14. What is the Difference Between persist() and merge()]]
- [[12. What is Dirty Checking in Hibernate]]
- [[17. How to Implement Optimistic Locking in JPA]]