spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.55k stars 40.54k forks source link

Hibernate Schema Validation filter is not working after upgrading to Spring Boot v3.0.1 #33832

Closed Andrej988 closed 1 year ago

Andrej988 commented 1 year ago

I am not sure if this is Spring or Hibernate issue, but after upgrading from Spring Boot 2.7.5 to 3.0.1 schema validation filter stopped working. Relevant properties:

spring.jpa.hibernate.ddl-auto: validate
spring.jpa.properties.hibernate.hbm2ddl.schema_filter_provider: [fully qualified name to custom schema filter provider]

Error Stack:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [application_settings]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1751) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1130) ~[spring-context-6.0.3.jar:6.0.3]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:905) ~[spring-context-6.0.3.jar:6.0.3]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[spring-context-6.0.3.jar:6.0.3]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.0.1.jar:3.0.1]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-3.0.1.jar:3.0.1]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[spring-boot-3.0.1.jar:3.0.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-3.0.1.jar:3.0.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-3.0.1.jar:3.0.1]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[spring-boot-3.0.1.jar:3.0.1]
    at si.initialised.services.geo.GeoServiceApplication.main(GeoServiceApplication.java:12) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-3.0.1.jar:3.0.1]
Caused by: jakarta.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [application_settings]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797) ~[spring-beans-6.0.3.jar:6.0.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747) ~[spring-beans-6.0.3.jar:6.0.3]
    ... 19 common frames omitted
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [application_settings]
    at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:133) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:46) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:96) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:74) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:293) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:143) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at java.base/java.util.HashMap.forEach(HashMap.java:1421) ~[na:na]
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:140) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:336) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.0.3.jar:6.0.3]
    ... 23 common frames omitted

NOTE: application_settings table is not in included tables in custom schema validation filter.

mhalbritter commented 1 year ago

If you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

spring-projects-issues commented 1 year ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

mrohlof-protofy commented 1 year ago

I don't have a Minimal Sample readily available, but I guess the problem is, that AbstractSchemaValidator receives the correct schemaFilter in constructor but then proceeds to never use it.

Instead it uses the SchemaFilter provided from ExecutionOptions in the doValidation method. Looks like a hibernate-core problem to me..?

wilkinsona commented 1 year ago

Thanks for trying to help, @mrohlof-protofy. It could well be a Hibernate problem but we won't be able to tell for sure without a sample from @Andrej988.

mrohlof-protofy commented 1 year ago

I am facing the same problem. Here you go.

Steps to reproduce

Actual behaviour 2.7.8: Test passes 3.0.2: Test fails because: Loading ApplicationContext fails because: Schema-validation: missing table [my_entity].

Expected behaviour "MyEntity" should be excluded from schema validation so that ApplicationContext can load properly.

#33832-minimal-example-springboot-3.0.2-fails.zip #33832-minimal-example-springboot-2.7.8-works.zip

The difference between both examples is: a) spring-boot-starter-parent version 2.7.8 -> 3.0.2 b) javax.persistence.* -> jakarta.persistence.*

wilkinsona commented 1 year ago

Thanks for the samples, @mrohlof-protofy. With them, I was able to see the hardcoded use of DefaultSchemaFilter.INSTANCE that you've reported in https://hibernate.atlassian.net/browse/HBX-2476. This will need to be fixed in Hibernate.

disk91 commented 8 months ago

Hello, any update on this ? it seems to continue to exist in spring 3.2.1 / Hibernate

bclozel commented 8 months ago

@disk91 you should follow the updates on the hibernate issue Andy linked above.

disk91 commented 8 months ago

I had a look at it, and nothing moved in 2023, that's a blocking bug in migration path. As no-one seems to act on Hibernate, is there a working bypass known ?

mimranfaruqi commented 8 months ago

I am working with Quarkus whose version 3.6.5 uses Hibernate 6 and having problem with validating only one column. Everything else works just fine. All other columns within the same table works just fine, but a specific column cannot be matched with the column in database. I am using @Column annotation on class member. Apart from that, I am using SnakeCase naming strategy. The complain is that Hibernate cannot find the column my_column where as @Column("myColumn") is already present on the class member. I can also find the column "myColumn" in the database as is. If I create another column "my_column" in database, the error goes. But production database also uses "myColumn" convention and hence I cannot just change it.

instagibb commented 7 months ago

@disk91 We have worked around it by abstracting a layer higher so the correct schema filter is used instead of the default one

Hibernate allows you to specify hibernate.schema_management_tool instead Then you can extend HibernateSchemaManagementTool and override getSchemaValidator to make sure your custom schema filter is used.

For us this meant also extending GroupedSchemaValidatorImpl and overriding performValidation and ensuring the configured SchemaFilter (part of AbstractSchemaValidator) is used instead of DefaultSchemaFilter.INSTANCE

Hope that helps

SteMoeller commented 6 months ago

GroupedSchemaValidatorImpl

You're my hero... thanks to your hints I was able to get our schema validator up and running againg... Had to follow your path though including my own GroupdedShemaValidator with overriding performValidation...

Yeah, that DID help! Thanks!

disk91 commented 6 months ago

@disk91 We have worked around it by abstracting a layer higher so the correct schema filter is used instead of the default one

Hibernate allows you to specify hibernate.schema_management_tool instead Then you can extend HibernateSchemaManagementTool and override getSchemaValidator to make sure your custom schema filter is used.

For us this meant also extending GroupedSchemaValidatorImpl and overriding performValidation and ensuring the configured SchemaFilter (part of AbstractSchemaValidator) is used instead of DefaultSchemaFilter.INSTANCE

Hope that helps

Thank you so much for replying, before I start to implement it, do you have an open source code implementing it to make sure I do it the right way ?

SteMoeller commented 6 months ago

Take a look here: https://hibernate.atlassian.net/browse/HHH-17763 Seems to be fixed in 6.5 and 6.4.5 if I am correct...

instagibb commented 6 months ago

Yes this has been fixed very recently although the bug has been there for over a year. This work around allowed us to get our Spring Boot 3 upgrade done while waiting for Hibernate to fix the bug (after 1 year we'd kinda lost hope it would be fixed). Hopefully we see Hibernate 6.4.5 in the next Spring Boot release