Every developer has those moments where a seemingly simple task turns into a head-scratching puzzle. This error, encountered while trying to configure a custom LocalSessionFactoryBean in Spring Boot, is a perfect example of a subtle type mismatch causing a cryptic failure.
The Scenario and the Error
The goal was to set up a custom SessionFactory bean using Spring’s LocalSessionFactoryBean. The initial, problematic configuration was:
@Configuration
public class HibernateConfig {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
// โฆ set data source, hibernate properties โฆ
// This line caused the error!
sessionFactory.setConfigurationClass(org.hibernate.cfg.Configuration.class);
return sessionFactory;
}
}
This configuration resulted in the following exception upon application startup:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory':
Bean property 'configurationClass' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?
Understanding the Core Problem
The error message, “Bean property ‘configurationClass’ is not writable or has an invalid setter method,” is a classic Spring message indicating a type mismatch when the container attempts to apply property values using the JavaBeans convention.
The Setter’s Expectation
The property in question is defined in AbstractSessionFactoryBean (the parent of LocalSessionFactoryBean):
// From org.springframework.orm.hibernate5.AbstractSessionFactoryBean
@Nullable private Class<? extends Configuration> configurationClass; // The property type
public void setConfigurationClass(@Nullable Class<? extends Configuration> configurationClass) {
this.configurationClass = configurationClass;
}
The setConfigurationClass method expects a Class object that is a subclass of org.hibernate.cfg.Configuration.
The Mistake: Confusing Instance vs. Type
The mistake was assuming that the method was missing or invalid. It turns out the error was in the usage:
- Intention: The developer likely intended to use the default Hibernate
Configurationor perhaps set configuration properties. - The Setter’s Role (
setConfigurationClass): This method is for specifying a custom subclass oforg.hibernate.cfg.Configurationfor Spring to use when creating the actual configuration. - The Misleading Argument: The argument passed was
org.hibernate.cfg.Configuration.class, which is syntactically aClassobject, but it’s redundant, as this is the default class used byLocalSessionFactoryBean. The error may occur if the Spring container’s reflection mechanism doesn’t perfectly resolve the generic typeClass<? extends Configuration>.
The core takeaway is: LocalSessionFactoryBean expects a Class type for setConfigurationClass, and an instance of Configuration for setConfiguration.
The Solution: Correct Configuration Methods
There are two correct approaches, depending on what you truly need to achieve:
Option 1: Providing a Configured Configuration Instance
If you need to programmatically build and provide a fully configured org.hibernate.cfg.Configuration instance, use setConfiguration(Configuration configuration):
import org.hibernate.cfg.Configuration; // Ensure this is org.hibernate.cfg.Configuration
// ... inside the @Bean method ...
// OPTION 2: If you want to provide an already instantiated Configuration object
Configuration hibernateConfiguration = new Configuration();
// Add specific properties and settings to the instance here...
sessionFactory.setConfiguration(hibernateConfiguration);
Option 2: The Recommended Spring Boot Approach (Properties)
In most modern Spring/Hibernate applications, you typically let LocalSessionFactoryBean use its default Configuration class and provide settings using the dedicated setHibernateProperties method and setPackagesToScan. This is much cleaner and is usually what is required for granular control outside of Spring Boot’s automatic configuration.
@Configuration
public class HibernateConfig {
@Bean
public LocalSessionFactoryBean sessionFactory(/* inject DataSource dataSource */) {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
// sessionFactory.setDataSource(dataSource);
// Configure Hibernate properties directly:
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "update");
hibernateProperties.setProperty("hibernate.show_sql", "true");
// ... more properties ...
// This is the correct way to set configuration settings
sessionFactory.setHibernateProperties(hibernateProperties);
// Essential for Annotation-based entities
sessionFactory.setPackagesToScan("com.ankurm.model");
// No need to call setConfigurationClass or setConfiguration!
return sessionFactory;
}
}
The key to resolving the Bean property 'configurationClass' is not writable error is to avoid calling setConfigurationClass unless you genuinely have a custom subclass of org.hibernate.cfg.Configuration. For all other configuration needs, use setHibernateProperties or setConfiguration.
Frequently Asked Questions
Q1: When would I legitimately need to call setConfigurationClass()?
Only when you have a custom subclass of org.hibernate.cfg.Configuration that overrides internal Hibernate behaviour โ for example, a subclass that adds custom type mappings or interceptors at the configuration level. In that case, pass your class: sessionFactory.setConfigurationClass(MyCustomConfig.class). For all standard use cases, leave it unset and use setHibernateProperties instead.
Q2: Is this error related to Hibernate version compatibility?
Sometimes. In Spring 6 + Hibernate 6/7, the LocalSessionFactoryBean class is from the spring-orm module. If you are mixing a Spring 5 version of LocalSessionFactoryBean (which used javax.persistence) with Hibernate 7 (which uses jakarta.persistence), you will get class-loading failures. Ensure your spring-orm version matches your Spring Boot version.
Q3: Should I use LocalSessionFactoryBean or let Spring Boot auto-configure the SessionFactory?
For most Spring Boot applications, rely on Spring Boot’s auto-configuration (via spring-boot-starter-data-jpa). This auto-creates an EntityManagerFactory and exposes it as a SessionFactory if needed. Only use LocalSessionFactoryBean explicitly when you need the Hibernate-native Session API, multiple data sources, or configuration that Spring Boot’s auto-config cannot express through application.properties.
Q4: What is the difference between setConfiguration() and setHibernateProperties()?
setConfiguration(Configuration config) accepts a fully pre-built org.hibernate.cfg.Configuration instance that you have constructed and configured manually. setHibernateProperties(Properties props) is the standard declarative approach โ you pass a Properties map and Spring builds the configuration internally using those settings plus auto-discovered entities. For most applications, setHibernateProperties is simpler and less error-prone.
Q5: How do I configure multiple SessionFactories in the same Spring Boot app?
Define multiple LocalSessionFactoryBean beans, each with a distinct @Qualifier, pointing to different DataSource beans. Use setPackagesToScan to direct each factory to its own entity package, preventing cross-database entity scanning. In your repositories and services, inject the specific factory using @Qualifier("primarySessionFactory") or @Qualifier("secondarySessionFactory").
Conclusion
This error is a subtle type-mismatch caused by confusing setConfigurationClass(Class) โ which expects a subclass type reference โ with setConfiguration(Configuration) โ which expects an instance. In practice, most Spring Boot applications should not call either method; instead use setHibernateProperties for configuration values and setPackagesToScan for entity discovery, and let Spring’s LocalSessionFactoryBean handle the rest. Only reach for setConfigurationClass if you genuinely have a custom Configuration subclass.
Further Reading & Cross-References
- ๐ Hibernate 7 SessionFactory Bootstrapping (Without XML) โ the modern programmatic alternative to LocalSessionFactoryBean
- ๐ Hibernate 7 with Spring Boot 4 โ Spring Boot auto-configuration that removes the need for manual LocalSessionFactoryBean setup
- ๐ Hibernate 7 HikariCP Connection Pooling โ configuring the DataSource that backs the SessionFactory
- ๐ Spring LocalSessionFactoryBean Javadoc