Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align HibernateJpaVendorAdapter with Hibernate ORM 6.2 #30288

Closed
nemanjajovanovicgit opened this issue Apr 4, 2023 · 11 comments
Closed

Align HibernateJpaVendorAdapter with Hibernate ORM 6.2 #30288

nemanjajovanovicgit opened this issue Apr 4, 2023 · 11 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: documentation A documentation task type: enhancement A general enhancement
Milestone

Comments

@nemanjajovanovicgit
Copy link

Affects: spring-orm 6.0.7 and earlier

In application running spring 6.0.7 and hibernate 6.2.0.final, when spring is creating hibernate session factory in Spring application context exception occurs:

java.lang.NoSuchMethodError: 'void org.springframework.orm.hibernate5.LocalSessionFactoryBuilder.setImplicitNamingStrategy(org.hibernate.boot.model.naming.ImplicitNamingStrategy)'
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:547)
at com.epox.service.system.EpoxLocalSessionFactoryBean.afterPropertiesSet(EpoxLocalSessionFactoryBean.java:30)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1816)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766)

This is caused by the fact that in Hibernate 6.2 has changed return type for the method Configuration.setImplicitNamingStrategy (instead of void Configuration is returned).

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 4, 2023
@sbrannen sbrannen added the in: data Issues in data modules (jdbc, orm, oxm, tx) label Apr 5, 2023
@goetzseb
Copy link

goetzseb commented May 2, 2023

Same issue here for us.
Hibernate's org.hibernate.cfg.Configuration class has changed the return types of most methods to Configuration to support method chaining, I guess, which breaks the compatibility with the version used as dependency in spring-core 6.0.8 (org.hibernate hibernate-core-jakarta 5.6.15.Final).
The problem arises if using spring-core 6.x with hibernate-orm 6.x on the classpath. As in previous versions org.springframework.orm.hibernate5.LocalSessionFactoryBuilder bean is used to configure Hibernate. We do it with XML like this:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" depends-on="dataSource">
	<property name="dataSource" ref="dataSource" />
	<!-- entity search path -->
	<property name="packagesToScan" value="com.acme.model" />
	<property name="physicalNamingStrategy">
		<bean class="${hibernate.physical_naming_strategy}"/>
	</property>
	<!-- package-level annotation search path -->
	<property name="annotatedPackages">
		<list>
			<value>com.acme.model</value>
		</list>
	</property>
	<property name="hibernateProperties">
		<props>
			<!-- Qualify unqualified table names with the given schema/tablespace -->
			<prop key="hibernate.default_schema">${hibernate.default_schema}</prop>
			<!-- Use a customer schema name resolver since hibernate's default resolver is a little naive -->
			<prop key="hibernate.schema_name_resolver">${hibernate.schema_name_resolver}</prop>
			<!-- SQL dialect -->
			<prop key="hibernate.dialect">${hibernate.dialect}</prop>
			<!-- The second-level cache -->
			<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
			<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
			<!-- Enable query cache -->
			<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
			<!-- Echo all executed SQL to stdout -->
			<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
			<!-- Enable statistics -->
			<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
			<!-- Pretty print the SQL in the log and console. -->
			<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
			<!-- Prevents hibernate default save or update listener from throwing PropertyValueException prior to our entity listener being called -->
			<prop key="hibernate.check_nullability">false</prop>
			<!-- Maintain backwards compatibility for id generators to support existing databases -->
			<prop key="hibernate.id.new_generator_mappings">${hibernate.id.new_generator_mappings}</prop>
			<!-- Allow alternative naming strategy for physical table names -->
			<prop key="hibernate.physical_naming_strategy">${hibernate.physical_naming_strategy}</prop>
			<!-- Allow alternative naming strategy for physical table names -->
			<prop key="hibernate.globally_quoted_identifiers">${hibernate.globally_quoted_identifiers}</prop>
			<!-- Allow lazy initialization w/o detached objects -->
			<prop key="hibernate.enable_lazy_load_no_trans">${hibernate.enable_lazy_load_no_trans}</prop>

			<!-- ORACLE SPECIFICS -->
			<!-- Stick to LONG RAW data type for backward compatibility -->
			<prop key="hibernate.dialect.oracle.prefer_long_raw">${hibernate.dialect.oracle.prefer_long_raw}</prop>
		</props>
	</property>
</bean>

When the org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet() method is called after the bean is initialized, a LocalSessionFactoryBuilder instance is used to setup the SessionFactory.

Workaround:
We have overridden this method with hibernate.orm 6.2.1 on the classpath to compile against the most current org.hibernate.cfg.Configuration class version. But it is a very nasty solution which requires Reflection, because most of the properties are not accessible otherwise.

@snicoll snicoll removed their assignment May 2, 2023
@BladeWise
Copy link

The problem can be seen even looking at the current LocalSessionFactoryBuilder source code for setCurrentTenantIdentifierResolver (spring-orm 6.0.9).

As stated above, on Hibernate 6.0+ this override should return a Configuration, so the current LocalSessionFactoryBuilder is not compatible with 6.0+.
Given that LocalSessionFactoryBuilder is delcared in the hibernate5 package, is it expected that it is not compliant with 6.0, and an alternative approach should be used?
As far as I can see, Hibernate 6.2 should be supported since Spring 6.0.4 release.

@snicoll
Copy link
Member

snicoll commented May 22, 2023

The compatibility you're talking about is via the JPA persistence provider API, not the Hibernate API. We don't have a commitment for the latter and we expect most users to configure their apps via JPA.

@BladeWise
Copy link

If this is the case, can we assume LocalSessionFactoryBuilder is a deprecated functionality, and the only available support for Hibernate 6.0+ is through the JPA persistence provider API?
In my case, I was supporting both APIs even if the JPA is the one being actually used by the application, and removing the LocalSessionFactoryBuilder bean fixes the issue.

@jezovuk
Copy link

jezovuk commented May 23, 2023

The problem is indeed caused by changes in Hibernate's Configuration class, but it seems to me that it only affects Spring integration with Hibernate 6.2+, not 6.0.x and 6.1.x. See the original Hibernate commit here: hibernate/hibernate-orm@7b493f3#diff-ae5690e4fc2a7db82608af8ed7fd93334ae9b5b97cc2b86b63f62a4a0870e8c2.

If LocalSessionFactoryBuilder is to remain available and supported, I guess there should be a way to support both Hibernate 5.x - 6.1.x and Hibernate 6.2.x. Perhaps separate spring-orm artefact built against Hibernate 6.2+?

@snicoll
Copy link
Member

snicoll commented May 23, 2023

The purpose of this very issue is to investigate a solution…

@BladeWise
Copy link

In my opinion, the solution could be the same that has been used previously in spring-orm when switching Hibernate support from 3 to 4, and from 4 to 5.
Checking the history of this repository, it seems that spring-orm was initially supporting the previous version of Hibernate, providing an additional module for the new version (see tag 3.0.x vs tag 4.0.x), but later on it started providing support only to the latest version (see tag 5.0.x).
Following this pattern, 6.0.x should either provide a spring-orm-hibernate6 module (or modules, given @jezovuk comment on the minor-version breaking change), or eventually drop support for Hibernate 5 in favor of Hibernate 6.2.

@snicoll
Copy link
Member

snicoll commented May 23, 2023

Thanks @BladeWise, but we know what our options are.

@jhoeller
Copy link
Contributor

jhoeller commented May 23, 2023

If this is the case, can we assume LocalSessionFactoryBuilder is a deprecated functionality, and the only available support for Hibernate 6.0+ is through the JPA persistence provider API?

That's the case indeed for such purposes. While the orm.hibernate5 package is not technically deprecated, it is exclusively meant to be used with Hibernate ORM 5.x as per the package name. The javadoc explicitly states compatibility with Hibernate ORM 5.5/5.6.

FWIW, LocalSessionFactoryBuilder is only part of the problem there. HibernateTemplate and co have even stronger compatibility issues against Hibernate ORM 6. The parallel maintenance of an orm.hibernate5 or potential orm.hibernate6 package is not justifiable against Hibernate ORM 6 anymore, given how omnipresent JPA-style setup is in recent years.

All things considered, Hibernate ORM 6.x is only supported via JPA, by design. We have dedicated Hibernate support there in the form of HibernateJpaVendorAdapter, supporting Hibernate provider specifics. It currently claims compatibility with 5.5/5.6 as well as 6.0/6.1; I'll make sure to document it for Hibernate ORM 6.2 as well.

@jhoeller jhoeller added type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels May 23, 2023
@jhoeller jhoeller self-assigned this May 23, 2023
@jhoeller jhoeller added this to the 6.0.10 milestone May 23, 2023
@jhoeller jhoeller changed the title Compatibility with Hibernate ORM 6.2 Document compatibility with Hibernate ORM 6.2 May 23, 2023
@jhoeller jhoeller changed the title Document compatibility with Hibernate ORM 6.2 Document compatibility with Hibernate ORM 6.2 as a JPA provider May 23, 2023
@jhoeller jhoeller changed the title Document compatibility with Hibernate ORM 6.2 as a JPA provider Align HibernateJpaVendorAdapter with Hibernate ORM 6.2 May 23, 2023
@jhoeller jhoeller added the type: enhancement A general enhancement label May 23, 2023
@jhoeller
Copy link
Contributor

It turns out that there is actually a bit of alignment to do: Hibernate 6.2 removed deprecated dialect classes for Derby and PostgreSQL, so we have to use replacements there now for our purposes in HibernateJpaVendorAdapter. This only applies for explicit use of the Database enum which is not common since Hibernate's database autodetection works quite well anyway, but nevertheless, we need to consistently select a working dialect with Hibernate 6.2 there as well.

@andersb
Copy link

andersb commented Mar 1, 2024

I found this issue during my migration from Spring Boot 2.7 to 3.2 which have proven to be quite challenging :)

I decided several years ago to remove JPA (v2.x at the time) configuration in favor of using Spring/Hibernate with LocalSessionFactoryBean because I kept running into the fact that I needed to unwrap the entity manager to Session in order to use hibernate specific features.
Now, JPA have of course evolved but even in Jakarta JPA 3.1, there are still features I use in Hibernate which requires unwrapping.

And configuration wise, LocalSessionFactoryBean feels a lot more straight forward and easy to use, in my opinion. (But I must admit, that comes from the fact that I'm a lot more used to this type of configuration).

So, I just wanted to mention that there would be at least 1 vote for having a orm.hibernate6.LocalSessionFactoryBean :)

I got everything working with Spring Boot 3.2 and Hibernate 5.6 so I will stick with that for now.
Been using Spring Framework since v1.2.8, keep up the good work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: documentation A documentation task type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

9 participants