4

How to validate the DDL schema with Spring and Hibernate

 1 year ago
source link: https://vladmihalcea.com/validate-ddl-schema-spring-hibernate/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

The best way to validate the DDL schema with Spring and Hibernate

Last modified: Jun 8, 2023

Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn’t that be just awesome?

Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.

So, enjoy spending your time on the things you love rather than fixing performance issues in your production system on a Saturday night!

Introduction

In this article, we are going to see what is the best way to validate the DDL schema and the JPA entity mappings when using Spring and Hibernate.

I decided to write this article after reading this Tweet:

Hi Vlad, shouldn't we set the value of spring.jpa.hibernate.ddl-auto=validate so that we are checking that flyway generated tables and our entities are in sync??

— Raja Dilip Kolli (@rajadilipkolli) June 5, 2023

The hbm2ddl validate strategy

As I explained in this article, Hibernate provides a SchemaManagementTool that we can use to manage or validate the underlying database schema.

While generating the DDL scripts with this Hibernate tool can be useful only to determine the DB schema that Hibernate expects for the current JPA entity mappings, it’s best to use an automatic schema management tool, like Flyway, to manage your database schema.

However, the Hibernate SchemaManagementTool also offers a validate strategy that can verify whether the JPA entity mappings are compatible with the underlying database schema.

In Spring, you can activate this strategy via the spring.jpa.hibernate.ddl-auto application property:

spring.jpa.hibernate.ddl-auto=validate

Once you provide this setting, the validation will be done every time you bootstrapped Hibernate.

However, since integration tests are meant to run in isolation, it’s common to create and destroy the Hibernate schema for every test execution, and validating the schema for every test execution is just adding an unnecessary overhead.

We can actually measure this overhead like this:

SchemaValidator schemaValidator = getSchemaValidator(sessionFactory);
final ExecutionOptions executionOptions = SchemaManagementToolCoordinator
.buildExecutionOptions(
settings,
ExceptionHandlerHaltImpl.INSTANCE
);
long startNanos = System.nanoTime();
schemaValidator.doValidation(
metadataImplementor,
executionOptions
);
LOGGER.info(
"Schema validation took: [{}] ms",
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos)
);

When running this test on Shopizer, which is a non-trivial Spring Boot project with over 100 JPA entities, this is what I get printed in the log:

SchemaValidationTest : Schema validation took: [138] ms

So, if the validation takes 138 milliseconds on every test execution and we have 1000 tests, then the overall overhead of the spring.jpa.hibernate.ddl-auto=validate setting is going to be 2 minutes and 18 seconds.

Not nice!

Now, you may wonder why you’d even need such a validation if you’re already using Flyway or Liquibase to manage your schema.

Even if you are using an automated schema management tool, if you are using JPA, then you must make sure that the entity mappings are compatible with the underlying database schema. Otherwise, your application is not going to work as expected, as the JPA provider might assume a different database schema than the actual one.

So, the purpose of this validation check is to ensure that the JPA entity mappings are compatible with the underlying database schema.

The best way to validate the DDL schema with Spring and Hibernate

Now that we have seen that it’s not useful to validate the schema every time Hibernate bootstraps, let’s see how we can disable the global validation.

To disable the global schema validation, we just need to set the spring.jpa.hibernate.ddl-auto property to the value of none:

spring.jpa.hibernate.ddl-auto=none

Having disabled the global schema validation, we can now activate the spring.jpa.hibernate.ddl-auto=validate setting only for a single Spring test like this:

@DataJpaTest(
properties = "spring.jpa.hibernate.ddl-auto=validate"
)
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class SchemaValidationTest {
@Test
public void testSchemaValidity() {}
}

This way, we can still validate the schema, but we do it only once instead of doing it every time the JPA EntityManagerFactory is bootstrapped.

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.

Conclusion

Validating the DDL schema with the JPA mappings is a very important task, but you should not do that every time Spring runs an integration test because the validation overhead will just add up to the overall time it takes to run your test suite.

By validating the database schema only once, you get exactly the outcome you wanted from the very beginning, but without paying the extra overhead every time you bootstrap JPA and Hibernate.

Transactions and Concurrency Control eBook

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Comment *

Before posting the comment, please take the time to read the FAQ page

Name *

Email *

Website

Notify me of follow-up comments by email.

This site uses Akismet to reduce spam. Learn how your comment data is processed.


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK