I am trying to set up my new Spring Boot 3.1.5 project. And I found one problem with Hibernate during it. Let me show you my setup:
pom.xml - dependencies
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
as you can notice I use spring-boot-starter-data-jpa which contains hibernate dependency -
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.2.13.Final</version>
<scope>compile</scope>
</dependency>
my Hibernate setup
// setup Hibernate LocalSessionFactoryBean
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource appDataSource) {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(appDataSource);
sessionFactory.setPackagesToScan(...);
sessionFactory.setPhysicalNamingStrategy(new AppPhysicalNamingStrategy());
// Hibernate properties
final Properties hibernateProperties = new Properties();
...
sessionFactory.setHibernateProperties(hibernateProperties);
return sessionFactory;
}
// Changing transaction manager to hibernate
@Bean
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory);
return transactionManager;
}
Plus I use @EnableTransactionManagement
Everything worked fine until I used setPhysicalNamingStrategy. From that moment I could not start my project due to the following:
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:555)
The following method did not exist:
'void org.springframework.orm.hibernate5.LocalSessionFactoryBuilder.setPhysicalNamingStrategy(org.hibernate.boot.model.naming.PhysicalNamingStrategy)'
The calling method's class, org.springframework.orm.hibernate5.LocalSessionFactoryBean, was loaded from the following location:
jar:file:.../.m2/repository/org/springframework/spring-orm/6.0.13/spring-orm-6.0.13.jar!/org/springframework/orm/hibernate5/LocalSessionFactoryBean.class
The called method's class, org.springframework.orm.hibernate5.LocalSessionFactoryBuilder, is available from the following locations:
jar:file:.../.m2/repository/org/springframework/spring-orm/6.0.13/spring-orm-6.0.13.jar!/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.class
The called method's class hierarchy was loaded from the following locations:
org.springframework.orm.hibernate5.LocalSessionFactoryBuilder: file:.../.m2/repository/org/springframework/spring-orm/6.0.13/spring-orm-6.0.13.jar
org.hibernate.cfg.Configuration: file:.../.m2/repository/org/hibernate/orm/hibernate-core/6.2.13.Final/hibernate-core-6.2.13.Final.jar
Action:
Correct the classpath of your application so that it contains compatible versions of the classes org.springframework.orm.hibernate5.LocalSessionFactoryBean and org.springframework.orm.hibernate5.LocalSessionFactoryBuilder
So the problem is with the method setPhysicalNamingStrategy which is not determined during the build.
I tried to delete my .m2 folder and reimport all dependencies again, restart IDE, mvn clean package and none of these work.
I also found one solution, when I add another hibernate property:
hibernateProperties.setProperty("hibernate.physical_naming_strategy", AppPhysicalNamingStrategy.class.getName());
However, I am not completely satisfied with this because I still don't understand why the method is available in the code and not available during the build.
So my question is why this happens? Or is there something wrong with my dependencies, what else i can do?
I will be really glad for your help. Thanks for your help all
Old question but someone might end up here for the same reason I did. I've run into similar problem when upgrading from Spring Boot 2.7.x / Hibernate 5.8.x to 3.2.x / 6.4.x
The main issue is that Hibernate 6.x can't really be used directly in Spring Framework 6.x.
From https://docs.spring.io/spring-framework/reference/data-access/orm/hibernate.html
Meaning, the LocalSessionFactoryBean, which resides in the org.springframework.orm.hibernate5 package, does not work with creating SessionFactories for Hibernate 6.x.
However, I did manage to get this working a bit by extending LocalSessionFactoryBean.
Using this class, you don't run into the issue that a method is missing. Now, I didn't pursue this solution because it feels a bit "hacky" and I'm unsure what consequences it might lead to down the road.
There is probably a reason why LocalSessionFactoryBean wasn't updated to support Hibernate 6.x so I'm in the process of implementing Hibernate as a JPA provider.