Recently I got the chance to review Vlad Mihalcea's Hypersistence Optimizer. It…
checks your JPA and Hibernate mappings and provides you tips about how you can optimize your application
For evaluating this tool I picked one of the main applications (Spring Boot 2.1 and Java 8) of my current project. With this blog post, I'll share my review with you.
TL;DR:
- simple to use and integrate
- book Vlad Mihalcea's in-depth JPA & Hibernate knowledge as a service with this tool
- automate the process of finding JPA & Hibernate code smells in your application
Project setup for the Hypersistence Optimizer
Vlad distributes the library via his teachable site. Once you buy your license, you get access to a new course and can download the hypersistence-optimizer-pack
.
Next, you have to unzip the content and install the content in your local Maven repository. Vlad provides a shell and batch file for this:
1 2 3 4 | unzip hypersistence-optimizer-1.3.0-pack.zip cd hypersistence-optimizer-1.3.0 chmod +x maven-install.sh ./maven-install.sh |
Once the Hypersistence Optimizer is available in your local Maven repository, you can start using it:
1 2 3 4 5 | <dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-optimizer</artifactId> <version>1.3.0</version> </dependency> |
Analyzing the application's JPA & Hibernate setup
There are multiple ways to get the output of the Hypersistence Optimizer. If you are using Spring Boot with Spring Data JPA, you can create the following component, which will run after your Spring Boot application starts:
1 2 3 4 5 6 7 8 9 10 11 12 | @Component public class HypersistenceAnalyzer implements CommandLineRunner { @PersistenceUnit private EntityManagerFactory entityManagerFactory; @Override public void run(String... args) throws Exception { System.out.println("Analyzing JPA & Hibernate setup"); new HypersistenceOptimizer(new JpaConfig(entityManagerFactory)); } } |
You can also write an integration test and get the Hypersistence Optimizer output while executing it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @DataJpaTest @ExtendWith(SpringExtension.class) class HypersistenceAnalyzerTest { @PersistenceUnit private EntityManagerFactory entityManagerFactory; @Test public void testOptimizer() { new HypersistenceOptimizer( new JpaConfig(entityManagerFactory) ); } } |
Make sure to use the same database (e.g. no H2) and the same Hibernate configurations as in production. Otherwise, the suggestions might not help that much. A development environment might be a good fit for this.
Once you run your application or execute the test, the Hypersistence Optimizer will print all findings with an indicator for its importance (BLOCKER
, CRITICAL
, MAJOR
, MINOR
)
1 2 3 4 5 6 7 8 | ERROR --- [main] Hypersistence Optimizer : CRITICAL - UnidirectionalOneToManyJoinTableEvent - The [tags] one-to-many association INFO --- [main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect WARN --- [main] Hypersistence Optimizer : MAJOR - SkipAutoCommitCheckEvent - You should set the [hibernate.connection.provider_disables_autocommit] ERROR --- [main] Hypersistence Optimizer : CRITICAL - JdbcBatchSizeEvent - If you set the [hibernate.jdbc.batch_size] configuration property ERROR --- [main] Hypersistence Optimizer : CRITICAL - JdbcFetchSizeEvent - If you set the [hibernate.jdbc.fetch_size] configuration property ERROR --- [main] Hypersistence Optimizer : BLOCKER - SchemaGenerationEvent - You should not set the [hibernate.hbm2ddl.auto] ERROR --- [main] Hypersistence Optimizer : CRITICAL - QueryPaginationCollectionFetchingEvent - You should set the [hibernate.query.fail_on_pagination_over_collection_fetch] WARN --- [main] Hypersistence Optimizer : MAJOR - QueryInClauseParameterPaddingEvent - You should set the [hibernate.query.in_clause_parameter_padding] |
For those of you who are using WildFly with Java EE or Jakarta EE, a simple setup can look like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Startup @Singleton public class JpaAnalyzer { @PersistenceUnit private EntityManagerFactory entityManagerFactory; @PostConstruct public void init() { System.out.println("Analyzing JPA & Hibernate setup"); new HypersistenceOptimizer(new JpaConfig(entityManagerFactory)); } } |
Unfortunately, you can't use it for applications running on Payara or Open Liberty (without configuring the JPA provider manually) as they use EclipseLink for the JPA implementation.
Summary of the Hypersistence Optimizer
I've tested it for one of my current applications and the suggestions/findings were really helpful. The result of the first run was the following:
1 | Hypersistence Optimizer: 272 issues were found: 0 BLOCKER, 26 CRITICAL, 195 MAJOR, 51 MINOR |
Most of the issues for this application where about fetching strategies and enum handling. Once I fixed one of the issues I was able to get instant feedback as I can re-run my Hypersistence Optimizer check. This allows you to tackle each individual suggestion step-by-step with short feedback cycles.
In conclusion, Hypersistence Optimizer is simple to use and integrate. Each warning comes with a link to a detailed description that contains a detailed blog post from Vlad. Furthermore, it provides great optimization support and inverts the process of fixing JPA & Hibernate issues as the tool tells you right-before where the root cause might be.
With this tool, you are able to book Vlad's in-depth JPA & Hibernate knowledge as a service. Knowing all JPA & Hibernate pitfalls is hard but with the Hypersistence Optimizer, you can automate the process of finding JPA & Hibernate code smells in your application.
Find further resources on Hypersistence Optimizer here:
- GitHub repository with different Spring application setups from Vlad
- Vlad's High-Performance Java Persistence Book
- Hypersistence Optimizer User Guide
- Official page of Hypersistence Optimizer
For more input on High-Performance Java persistence, have a look at Vlad's excellent online course.
PS: There is also a trial version available and you can find the source code for this Hypersistence Optimizer review on GitHub.
Have fun using the Hypersistence Optimizer,
Phil