Common Hibernate Interview Questions for Spring Developers: A Code-Deep Guide

The most effective Hibernate interview questions focus on how Spring Framework integrates with Hibernate through specific classes like LocalSessionFactoryBean and HibernateTransactionManager to manage sessions, transactions, and JPA abstractions.

When interviewing candidates for Spring-backed positions, understanding the bridge between Spring's transaction management and Hibernate's ORM capabilities separates proficient developers from those who merely configure XML. This guide examines the critical integration points in the spring-projects/spring-framework repository, referencing actual source files like LocalSessionFactoryBean.java and HibernateTransactionManager.java to explain the architectural decisions behind common hibernate interview questions.

SessionFactory Bootstrap and Configuration

How Spring Creates the Hibernate SessionFactory

The SessionFactory is Hibernate's heavyweight, thread-safe factory for Session objects. In org.springframework.orm.jpa.hibernate.LocalSessionFactoryBean, Spring wraps Hibernate's native Configuration class to provide dependency injection and lifecycle management.

The bootstrap logic resides in afterPropertiesSet(), where the factory bean merges Spring-managed DataSource references, scan packages, and Hibernate properties before building the SessionFactory. This allows Spring to inject resources like connection pools and naming strategies that pure Hibernate XML cannot easily reference.

@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
    LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
    factory.setDataSource(dataSource);
    factory.setPackagesToScan("com.example.model");
    
    Properties props = new Properties();
    props.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
    props.put("hibernate.hbm2ddl.auto", "update");
    factory.setHibernateProperties(props);
    return factory;
}

Configuring Second-Level Caching

Spring exposes Hibernate's cache integration through LocalSessionFactoryBean#setCacheRegionFactory. By accepting a RegionFactory bean, Spring wires the second-level cache provider during the afterPropertiesSet() initialization phase, ensuring the cache is available before any sessions open.

@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource, 
                                              RegionFactory cacheRegionFactory) {
    LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setCacheRegionFactory(cacheRegionFactory); // Integrates cache provider
    return bean;
}

Session Lifecycle and Transaction Management

openSession() vs. getCurrentSession()

openSession() always creates a new Hibernate Session instance, requiring manual closure and disconnected from Spring's transaction synchronization.

getCurrentSession() returns a session bound to the current thread's transaction context. In org.springframework.orm.jpa.hibernate.HibernateTransactionManager, the doBegin() method binds the session to TransactionSynchronizationManager, ensuring that subsequent calls within the same thread receive the same session instance. This thread-bound approach enables the Open Session in View pattern and guarantees that lazy-loaded collections remain accessible within the transaction boundary.

Coordinating Hibernate with Plain JDBC

HibernateTransactionManager implements ResourceTransactionManager to expose the underlying JDBC Connection from the Hibernate Session as a Spring ConnectionHolder. In the doBegin() method, the manager binds this holder to the thread, allowing JdbcTemplate or direct DataSource access to participate in the same physical transaction without XA overhead.

When the transaction completes, doCleanupAfterCompletion() removes the binding and resets connection flags, ensuring proper resource cleanup.

// Both Hibernate and JdbcTemplate participate in the same transaction
@Transactional
public void mixedAccess() {
    // Hibernate operation
    Session session = sessionFactory.getCurrentSession();
    session.save(entity);
    
    // JDBC operation uses same Connection
    jdbcTemplate.update("INSERT INTO audit_log ...");
}

Transaction Isolation and Read-Only Flags

HibernateTransactionManager inspects the TransactionDefinition passed to doBegin(). When a read-only or specific isolation level is requested, it delegates to DataSourceUtils.prepareConnectionForTransaction() to configure the underlying JDBC connection before Hibernate begins the transaction. The connection state is restored in doCleanupAfterCompletion() to prevent connection pool contamination.

JPA Abstraction and Vendor Integration

HibernateJpaVendorAdapter Purpose

org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter is Spring's bridge between the standard JPA EntityManagerFactory and Hibernate-specific configuration. It sets the persistence provider to SpringHibernateJpaPersistenceProvider, configures the HibernateJpaDialect, and applies default properties like hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_HOLD or ON_CLOSE depending on the environment.

HibernateJpaDialect Responsibilities

This dialect translates Hibernate exceptions to Spring's DataAccessException hierarchy, determines the appropriate FlushMode for transactions, and handles connection preparation for JPA operations. It ensures that standard JPA annotations behave consistently with Spring's transaction semantics.

SpringHibernateJpaPersistenceProvider

Located in org.springframework.orm.jpa.vendor, this class subclasses Hibernate's HibernatePersistenceProvider to override createContainerEntityManagerFactory(). It integrates Spring's class-loader infrastructure and native-image hints, allowing Hibernate to work within Spring Boot's executable JAR structure and GraalVM native images.

Advanced Configuration Patterns

Implicit and Physical Naming Strategies

Spring allows configuration of Hibernate 5+ naming strategies through LocalSessionFactoryBean:

  • setImplicitNamingStrategy: Controls how logical names are derived from entity mappings when no explicit column/table name is specified.
  • setPhysicalNamingStrategy: Transforms logical names to actual database identifiers (e.g., converting camelCase to snake_case).

Both are applied during the LocalSessionFactoryBuilder phase in afterPropertiesSet().

@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
    LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setImplicitNamingStrategy(new ImplicitNamingStrategyJpaCompliantImpl());
    bean.setPhysicalNamingStrategy(new PhysicalNamingStrategyStandardImpl());
    return bean;
}

Multi-Tenancy Configuration

For schema-based or database-based multi-tenancy, Spring exposes MultiTenantConnectionProvider and CurrentTenantIdentifierResolver through LocalSessionFactoryBean. These are forwarded to LocalSessionFactoryBuilder to construct a multi-tenant-aware SessionFactory.

@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource,
        MultiTenantConnectionProvider multiTenantProvider,
        CurrentTenantIdentifierResolver tenantResolver) {
    
    LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setMultiTenantConnectionProvider(multiTenantProvider);
    bean.setCurrentTenantIdentifierResolver(tenantResolver);
    return bean;
}

Registering Custom Hibernate Interceptors

Interceptors can be registered at the SessionFactory level via LocalSessionFactoryBean#setEntityInterceptor, or transaction-scoped via HibernateTransactionManager#setEntityInterceptor. When using the transaction manager approach, doBegin() applies the interceptor via sessionFactory.withOptions().interceptor(...) when opening new sessions.

@Bean
public HibernateTransactionManager txManager(SessionFactory sessionFactory) {
    HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
    tm.setEntityInterceptor(new AuditInterceptor());
    return tm;
}

Open Session in View Pattern

The Open Session in View (OSIV) pattern keeps a Hibernate Session open during the entire HTTP request processing, including view rendering, to prevent LazyInitializationException when accessing unloaded associations.

Spring provides OpenSessionInViewFilter for Servlet environments and OpenSessionInViewInterceptor for Spring MVC. These components obtain a session from the SessionFactory in preHandle(), bind it to the thread via TransactionSynchronizationManager, and close it in afterCompletion(). Configuration details are documented in framework-docs/modules/ROOT/pages/data-access/orm/hibernate.adoc.

@Bean
public OpenSessionInViewInterceptor osivInterceptor(SessionFactory sessionFactory) {
    OpenSessionInViewInterceptor interceptor = new OpenSessionInViewInterceptor();
    interceptor.setSessionFactory(sessionFactory);
    interceptor.setSingleSession(true);
    interceptor.setFlushMode(FlushMode.MANUAL);
    return interceptor;
}

Summary

  • LocalSessionFactoryBean in org.springframework.orm.jpa.hibernate bootstraps the SessionFactory with Spring-managed datasources, caching, naming strategies, and multi-tenancy providers.
  • HibernateTransactionManager binds sessions to threads via TransactionSynchronizationManager in doBegin(), enabling getCurrentSession() and mixed JDBC/Hibernate transactions.
  • HibernateJpaVendorAdapter and SpringHibernateJpaPersistenceProvider bridge Hibernate with standard JPA and Spring Boot's runtime environment.
  • Naming strategies, second-level caching, and multi-tenancy are configured through specific setters on LocalSessionFactoryBean before afterPropertiesSet() executes.
  • OSIV is implemented via OpenSessionInViewFilter or OpenSessionInViewInterceptor to extend session lifecycle across the web request.
  • Custom interceptors can be injected either globally via the factory bean or per-transaction via the transaction manager's setEntityInterceptor() method.

Frequently Asked Questions

What is the difference between openSession() and getCurrentSession() in Spring-managed Hibernate?

openSession() creates a new standalone Hibernate Session that is not bound to any transaction context and must be manually closed. getCurrentSession() returns a session associated with the current thread's transaction, managed by HibernateTransactionManager through TransactionSynchronizationManager. According to the Spring Framework source code, the transaction manager binds the session during doBegin() and unbinds it during cleanup, ensuring that all operations within a @Transactional method share the same session and database connection.

How does Spring enable Hibernate to participate in the same transaction as JdbcTemplate?

HibernateTransactionManager implements ResourceTransactionManager and exposes the underlying JDBC Connection from the Hibernate Session as a ConnectionHolder bound to the thread. When JdbcTemplate executes, it retrieves this existing holder via DataSourceUtils, allowing SQL operations to use the same physical connection and transaction boundary as Hibernate operations. This coordination happens in the manager's doBegin() method and is cleaned up in doCleanupAfterCompletion().

What is the purpose of HibernateJpaVendorAdapter in Spring Boot applications?

HibernateJpaVendorAdapter configures Hibernate as the JPA provider for Spring's LocalContainerEntityManagerFactoryBean. It sets the persistence provider class to SpringHibernateJpaPersistenceProvider, configures the HibernateJpaDialect for exception translation and flush mode handling, and applies Hibernate-specific defaults for connection handling. This adapter allows applications to use standard JPA annotations (@Entity, @PersistenceContext) while Hibernate handles the underlying ORM implementation.

How do you configure schema-based multi-tenancy in Spring with Hibernate?

Schema-based multi-tenancy requires implementing MultiTenantConnectionProvider and CurrentTenantIdentifierResolver. In your Spring configuration, inject these beans into LocalSessionFactoryBean using setMultiTenantConnectionProvider() and setCurrentTenantIdentifierResolver(). During afterPropertiesSet(), LocalSessionFactoryBean passes these to LocalSessionFactoryBuilder, which constructs a SessionFactory that routes connections to different database schemas based on the tenant identifier resolved from the current context.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →