Table of Contents
Introduction
Hypersistence Optimizer is a dynamic analyzing tool that can scan your JPA and Hibernate application and provide you tips about the changes you need to make to entity mappings, configurations, queries, and Persistence Context actions to speed up your data access layer.
Once you have downloaded the Full or Trial version, you need to follow a series of steps in order to install Hypersistence Optimizer.
Step 1: Unzip the package
The first thing you need to do is to unzip the package you have just downloaded.
> unzip hypersistence-optimizer-2.7.1-pack.zip
After unzipping the project package, you will get the following file structure:
creating: hypersistence-optimizer-2.7.1/ creating: hypersistence-optimizer-2.7.1/lib/ inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-javadoc.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-sources.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-jre6-javadoc.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-jre6-sources.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-jre6.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-jakarta-javadoc.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-jakarta-sources.jar inflating: hypersistence-optimizer-2.7.1/lib/hypersistence-optimizer-2.7.1-jakarta.jar creating: hypersistence-optimizer-2.7.1/docs/ creating: hypersistence-optimizer-2.7.1/docs/html/ creating: hypersistence-optimizer-2.7.1/docs/pdf/ inflating: hypersistence-optimizer-2.7.1/docs/html/asciidoctor.css inflating: hypersistence-optimizer-2.7.1/docs/html/coderay-asciidoctor.css inflating: hypersistence-optimizer-2.7.1/docs/pdf/InstallationGuide.pdf inflating: hypersistence-optimizer-2.7.1/docs/html/InstallationGuide.html inflating: hypersistence-optimizer-2.7.1/docs/html/UserGuide.html inflating: hypersistence-optimizer-2.7.1/docs/pdf/UserGuide.pdf inflating: hypersistence-optimizer-2.7.1/changelog.txt inflating: hypersistence-optimizer-2.7.1/LICENSE.txt inflating: hypersistence-optimizer-2.7.1/archiva-deploy.bat inflating: hypersistence-optimizer-2.7.1/archiva-deploy.sh inflating: hypersistence-optimizer-2.7.1/maven-install.bat inflating: hypersistence-optimizer-2.7.1/maven-install.sh inflating: hypersistence-optimizer-2.7.1/README.txt
The package contains the following resources:
- the
lib
folder contains the mainjar
file, as well as the JavaDoc and the Java sources - the
docs
folder contains the Installation and User Guides - the
changelog
file contains the release notes for all product versions - the
LICENSE
file contains the project license info - the
maven-install
scripts allow you to install the Java artifacts in your local Maven repository - the
README
file contains a short description of the project
Note that the documentation folder is not available in the Trial version. For the Trail version, you can use the online documentation only.
Step 2: Installing the Maven dependency
Whether you are using Maven or Gradle, you need to install the Maven dependency to your local repository.
For Windows, use the maven-install.bat
script:
> maven-install.bat
For Unix-based systems (e.g., Linux, Mac OS), use the maven-install.sh
script:
> ./maven-install.sh
Now, the hypersistence-optimizer
Maven dependency is installed in your local repository.
Installing the Maven dependency using a public or private Maven repository
If you have a group license and want to share it with your team, then you have two options:
- The first and most convenient option is to use the public Hypersistence Maven Repository. If you want to use this option, then please contact support so that we can register you an account on the public repository.
- The second option is to use a private Maven repository, like Apache Archiva or JFrog Artifactory.
Installing the Maven dependency on Apache Archiva (Optional Step)
The following Apache Archiva installation step is optional, so only consider it if you plan on sharing your Hypersistence Optimizer library with your team because you purchased a group license and don’t want to use the public Hypersistence repository that we can provide you access to.
If you haven’t yet installed Apache Archiva, you can either use this guide or by following these steps.
After downloading the latest version, you need to unzip it, go to the bin folder, and run the following two commands:
> archiva install > archiva start
After running these commands, Archiva will start a web application, which, by default, can be accessed at the localhost:8080
address. You need to access this address and create an admin
user.
Afterward, you need to navigate to the Maven M2_HOME
folder and configure the settings.xml
configuration file so that you add the following two server
XML tags in the servers
parent tag:
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- Other XML tags are omitted for brevity --> <servers> <server> <id>archiva.internal</id> <username>admin</username> <password>${archiva-admin-password}</password> </server> <server> <id>archiva.snapshots</id> <username>admin</username> <password>${archiva-admin-password}</password> </server> </servers> <!-- Other XML tags are omitted for brevity --> </settings>
Note that you need to replace the ${archiva-admin-password}
placeholders with the Archiva admin
user password that you set previously.
Afterward, you can use the archiva-deploy
scripts provided in the project pack:
For Windows, use the archiva-deploy.bat
script:
> archiva-deploy.bat http://localhost:8080/repository/internal/ archiva.internal
For Unix-based systems (e.g., Linux, Mac OS), use the archiva-deploy.sh
script:
> ./archiva-deploy.sh http://localhost:8080/repository/internal/ archiva.internal
Note that the archiva-deploy
script takes two arguments:
- The first argument is the URL where the Apache Archiva repository is located (e.g., `http://localhost:8080/repository/internal/`).
- The second argument is the Apache Archiva repository id where the artifacts are to be deployed (e.g.,
archiva.internal
).
Now, you need to go to the main pom.xml
Maven configuration file of your project and add the Apache Archiva repository
:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- Other XML tags are omitted for brevity --> <repositories> <repository> <id>archiva.internal</id> <name>Archiva 3rd-party Artifact Repository</name> <url>http://localhost:8080/repository/internal/</url> </repository> </repositories> <!-- Other XML tags are omitted for brevity --> <properties> <archiva-repository-id>archiva.internal</archiva-repository-id> <archiva-repository-url>http://localhost:8080/repository/internal/</archiva-repository-url> <!-- Other XML tags are omitted for brevity --> </properties> </project>
Note that you need to change the archiva-repository-id
and archiva-repository-url
properties to match your Apache Archiva repository settings.
Step 3: Adding the dependency to your project
Now, you need to add the hypersistence-optimizer
dependency to your project.
Step 3.1: Adding the dependency using Maven
If you are using Maven, then you need to add the following dependency tag to your pom.xml
configuration file:
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-optimizer</artifactId> <version>${hypersistence-optimizer.version}</version> </dependency>
The ${hypersistence-optimizer.version}
is a Maven property that you need to declare in the properties
tag of your pom.xml
configuration file like this:
<properties> ... <hypersistence-optimizer.version>2.7.1</hypersistence-optimizer.version> </properties>
Step 3.1.1: Add all-open if you’re using Kotlin with Maven
When using Kotlin, you need to use the all-open
compiler plugin.
First, you will need to add the kotlin-maven-allopen
dependency:
<dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-allopen</artifactId> <version>${kotlin.version}</version> </dependency>
Second, you need to configure the kotlin-maven-plugin
to use the all-open
compiler plugin:
<plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <configuration> <compilerPlugins> ... <plugin>all-open</plugin> </compilerPlugins> <pluginOptions> <option>all-open:annotation=javax.persistence.Entity</option> <option>all-open:annotation=javax.persistence.MappedSuperclass</option> <option>all-open:annotation=javax.persistence.Embeddable</option> </pluginOptions> </configuration> <executions> <execution> <id>compile</id> <goals> <goal>compile</goal> </goals> <configuration> <sourceDirs> <sourceDir>${project.basedir}/src/main/kotlin</sourceDir> <sourceDir>${project.basedir}/src/main/java</sourceDir> </sourceDirs> </configuration> </execution> <execution> <id>test-compile</id> <goals> <goal>test-compile</goal> </goals> <configuration> <sourceDirs> <sourceDir>${project.basedir}/src/test/kotlin</sourceDir> <sourceDir>${project.basedir}/src/test/java</sourceDir> </sourceDirs> </configuration> </execution> </executions> </plugin>
If you’re using Jakarta Persistence, you will need to replace the
javax.persistence
entries in theoption
XML elements withjakarta.persistence
.
Step 3.2: Adding the dependency using Gradle
If you’re using Gradle, then you should add the following dependency:
dependencies { ... implementation "io.hypersistence:hypersistence-optimizer:${hypersistenceOptimizerVersion}" }
The ${hypersistenceOptimizerVersion}
is a Gradle property which you need to declare in the ext
block:
ext { ... hypersistenceOptimizerVersion = '2.7.1' }
Also, when using Gradle, make sure that you add the mavenLocal()
to your build.gradle
configuration file.
repositories { mavenCentral() mavenLocal() }
Step 3.2.1: Add all-open if you’re using Kotlin with Gradle
If you are using Kotlin, you need to use the all-open
compiler plugin.
This can be done as follows:
buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version" } } apply plugin: "kotlin-allopen" allOpen { annotations( "javax.persistence.Entity", "javax.persistence.MappedSuperclass", "javax.persistence.Embedabble" ) }
If you’re using Jakarta Persistence, you will need to replace the
javax.persistence
entries that are passed to theannotations
method with theirjakarta.persistence
counterparts.
Jakarta Persistence
Therefore, from Hibernate 6 onwards, you should use the jakarta
classifier when declaring the Hypersistence Optimizer dependency.
For Maven, the classifier
XML tag of the hypersistence-optimizer
dependency must be set like this:
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-optimizer</artifactId> <version>2.7.1</version> <classifier>jakarta</classifier> </dependency>
Java 6 and 7
If your application is running on Java 6 or 7, you should use the jre6
classifier.
Therefore, for Maven, the classifier
XML tag of the hypersistence-optimizer
dependency must be set like this:
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-optimizer</artifactId> <version>2.7.1</version> <classifier>jre6</classifier> </dependency>
Trial Version
If you’re using the Trial Version, then your dependency should end with the trial
suffix.
For Maven, the version
XML tag of the hypersistence-optimizer
dependency must be set like this:
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-optimizer</artifactId> <version>2.6.0-trial</version> </dependency>
You can use this GitHub branch for the trial version as it provides various Spring or Java EE examples that you can use with Trial Version to verify how the tool works.
Step 4: Logging settings
By default, all events are logged using the Hypersistence Optimizer
logger name. Based on the performance optimization event priority, Hypersistence Optimizer will trigger either an ERROR
, WARN
, or INFO
log message. For this reason, it’s best to enable the INFO
log level for the Hypersistence Optimizer
logger name.
Logback logging setting
If you’re using Logback, you need to add the following logger entry to the Logback XML configuration file:
<logger name="Hypersistence Optimizer" level="info"/>
Log4j 2 logging setting
If you’re using Log4j 2, you need to add the following logger entry to the Log4j 2 configuration file:
<logger name="Hypersistence Optimizer" level="info"/>
Notice that the
appender-ref
XML element used theConsole
appender. You need to change that to whatever appender or appenders you have defined in your log configuration file.
Log4j 1.x logging setting
If you’re using Log4j 1.x, you need to add the following logger entry to the log4j.properties
file:
log4j.category.Hypersistence\ Optimizer=INFO
Step 5: Decorating the Persistence Unit
While scanning the Persistence Unit (e.g., EntityManagerFactory
or SessionFactory
) metadata only requires access to the existing JPA EntityManagerFactory
or Hibernate SessionFactory
, to inspect the Persistence Context and the currently executing queries, Hypersistence Optimizer needs to decorate the JPA EntityManagerFactory
or Hibernate SessionFactory
and inject various performance-related checks at runtime.
Depending on the Hibernate version you are using, there are different ways you can decorate the JPA Persistence Unit.
To determine the Hibernate version your application is using, you can run the mvn dependency:tree
command.
For instance, when running the mvn dependency:tree
command in the root folder of this Spring Boot PetClinic GitHub fork:
> mvn dependency:tree
You will notice that the Hibernate ORM 5.3.9 version is used:
+- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.1.4.RELEASE:compile | +- org.hibernate:hibernate-core:jar:5.3.9.Final:compile
Once you know the Hibernate version you are using, you can proceed to decorate the JPA and Hibernate Persistence Unit.
Decorating the Persistence Unit using Hibernate 5
If you’re using Hibernate 5, you don’t need to do anything since the Hibernate SessionFactory
(even when using JPA with Hibernate),
is decorated automatically by the org.hibernate.boot.spi.SessionFactoryBuilderFactory
service loader mechanism.
The overhead added by the Hibernate SessionFactoryDecorator
is minimal. Because method calls are inlined, many runtime proxies used by frameworks like Spring or connection pools have a higher overhead than the approach taken by the SessionFactoryDecorator
.
If you want to disable the
SessionFactory
decoration process, then you have to set the following configuration property in anapplication.properties
orhibernate.properties
file:> hypersistence.enable_auto_session_factory_decoration=false >You can also provide this property as a Java System property when starting your application.
Setting the LocalSessionFactoryBean asynchronous bootstrap executor
If you are configuring a SimpleAsyncTaskExecutor
via the bootstrapExecutor
property of the LocalSessionFactoryBean
via the Java-based configuration:
@Bean public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean(); ... localSessionFactoryBean.setBootstrapExecutor(new SimpleAsyncTaskExecutor()); return localSessionFactoryBean; }
or XML configuration:
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> ... <property name="bootstrapExecutor"> <bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" /> </property> </bean>
Then, Spring will use a Proxy
when creating the SessionFactory
, which can cause issues when binding and referencing the current transaction context.
So, to avoid this kind of issue, you need to change the sessionFactory
definition, as follows.
For Java-based configuration, use this SessionFactory
definition:
@Bean public LocalSessionFactoryBean originalSessionFactory() { LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean(); ... localSessionFactoryBean.setBootstrapExecutor(new SimpleAsyncTaskExecutor()); return localSessionFactoryBean; } @Bean @Primary public SessionFactory sessionFactory(SessionFactory originalSessionFactory) { if(originalSessionFactory instanceof InfrastructureProxy) { InfrastructureProxy infrastructureProxy = (InfrastructureProxy) originalSessionFactory; return (SessionFactory) infrastructureProxy.getWrappedObject(); } return originalSessionFactory; }
And, for XML configuration, use this SessionFactory
definition instead:
<bean id="originalSessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> ... <property name="bootstrapExecutor"> <bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" /> </property> </bean> <bean id="sessionFactory" factory-bean="originalSessionFactory" factory-method="getWrappedObject" primary="true"> </bean>
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-hibernate-example
GitHub repository.
Decorating the Persistence Unit using Hibernate 4 and 3
Since the SessionFactoryBuilderFactory
mechanism was introduced in Hibernate 5, if you’re using Hibernate 4 or 3, you will need to decorate the JPA EntityManagerFactory
or the Hibernate SessionFactory
manually, as illustrated by the following configurations.
Decorating the Persistence Unit using Spring
If you’re using Spring, you can use either the Java-based configuration or the legacy XML configuration files. The following configuration examples will show you how to decorate the Persistence Unit manually using Spring when using either Hibernate 4 or 3.
Decorating the Persistence Unit using Spring and Hibernate 4
If you’re using Hibernate 4, then the Persistence Unit can be created either via a LocalSessionFactoryBean
or the LocalContainerEntityManagerFactoryBean
.
Decorating the Hibernate 4 SessionFactory programmatically with Spring Java-based configuration
To decorate the Hibernate SessionFactory
, you just need to pass the SessionFactory
reference to the decorate
method of the HypersistenceHibernatePersistenceProvider
class. For this reason, the LocalSessionFactoryBean
creates a bean, called originalSessionFactory
.
This is the bean you would have normally named sessionFactory
, but, in this case, it needs to have a different name as the sessionFactory
bean name is reserved for the Hypersistence Optimizer SessionFactory
, as illustrated by the following configuration:
@Bean public LocalSessionFactoryBean originalSessionFactory() { LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean(); localSessionFactoryBean.setDataSource(dataSource()); localSessionFactoryBean.setPackagesToScan(packagesToScan()); localSessionFactoryBean.setHibernateProperties(additionalProperties()); return localSessionFactoryBean; } @Bean @Primary public SessionFactory sessionFactory( SessionFactory originalSessionFactory) { return HypersistenceHibernatePersistenceProvider.decorate( originalSessionFactory ); }
First, we create the LocalSessionFactoryBean
, which will be used to create a SessionFactory
that’s decorated by the HypersistenceHibernatePersistenceProvider
class.
Notice that we used the @Primary
annotation on the decorated sessionFactory
bean method to instruct Spring that this bean should be used whenever a SessionFactory
dependency is needed.
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-hibernate4-example
GitHub repository.
Decorating the Hibernate 4 SessionFactory declaratively with Spring XML configuration
To decorate the Hibernate SessionFactory
using the legacy XML configuration, you just need to wrap the original SessionFactory
as illustrated by the following examples.
<bean id="originalSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>${packages.to.scan}</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> </bean> <bean id="sessionFactory" class="io.hypersistence.optimizer.hibernate.decorator.HypersistenceHibernatePersistenceProvider" factory-method="decorate" primary="true"> <constructor-arg ref="originalSessionFactory"/> </bean>
First, we create the LocalSessionFactoryBean
, which will be used to create a SessionFactory
that’s decorated by the HypersistenceHibernatePersistenceProvider
class.
Notice that we set the primary
attribute to true
on the decorated sessionFactory
bean configuration to instruct Spring that this bean should be used whenever a SessionFactory
dependency is needed.
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-hibernate4-example
GitHub repository.
Decorating the Hibernate 4 JPA EntityManagerFactory programmatically with Spring Java-based configuration
To decorate the JPA EntityManagerFactory
, you just need to pass the EntityManagerFactory
reference to the decorate
method of the HypersistenceHibernatePersistenceProvider
class:
@Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() { LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setPersistenceUnitName(persistenceUnitName()); entityManagerFactoryBean.setPersistenceProvider(new HibernatePersistenceProvider()); entityManagerFactoryBean.setDataSource(dataSource()); entityManagerFactoryBean.setPackagesToScan(packagesToScan()); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter); entityManagerFactoryBean.setJpaProperties(additionalProperties()); return entityManagerFactoryBean; } @Bean @Primary public EntityManagerFactory entityManagerFactory( LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) { return HypersistenceHibernatePersistenceProvider.decorate( entityManagerFactoryBean.getNativeEntityManagerFactory() ); }
First, we create the LocalContainerEntityManagerFactoryBean
, which will be used to create an EntityManagerFactory
that’s decorated by the HypersistenceHibernatePersistenceProvider
class.
Notice that we used the @Primary
annotation on the decorated entityManagerFactory
bean method to instruct Spring that this bean should be used whenever an EntityManagerFactory
dependency is needed.
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-jpa-hibernate4-example
GitHub repository.
Decorating the Hibernate 4 JPA EntityManagerFactory declaratively with Spring XML configuration
To decorate the JPA EntityManagerFactory
using the legacy XML configuration, you just need to wrap the original EntityManagerFactory
as illustrated by the following examples.
<bean id="entityManagerFactory" class="io.hypersistence.optimizer.hibernate.decorator.HypersistenceHibernatePersistenceProvider" factory-method="decorate"> <constructor-arg> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>${packages.to.scan}</value> </list> </property> <property name="jpaVendorAdapter" ref="jpaVendor"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> </bean> </constructor-arg> </bean>
Notice that we haven’t defined a LocalContainerEntityManagerFactoryBean
bean that will be decorated by the primary entityManagerFactory
, as we did for the Java-based configuration.
This time, we are just passing the LocalContainerEntityManagerFactoryBean
to the decorate
method of the HypersistenceHibernatePersistenceProvider
utility in order to create the EntityManagerFactory
bean.
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-hibernate4-example
GitHub repository.
Decorating the Persistence Unit using Spring and Hibernate 3
If you’re using Hibernate 3, then the Persistence Unit can be created either via an AnnotationSessionFactoryBean
or the LocalContainerEntityManagerFactoryBean
.
Decorating the Hibernate 3 SessionFactory programmatically with Spring Java-based configuration
To decorate the Hibernate SessionFactory
, you just need to pass the SessionFactory
reference to the decorate
method of the HypersistenceHibernatePersistenceProvider
class.
For this reason, the AnnotationSessionFactoryBean
creates a bean, called originalSessionFactory
.
This is the bean you would have normally named sessionFactory
, but, in this case, it needs to have a different name as the sessionFactory
bean name is reserved for the Hypersistence Optimizer SessionFactory
, as illustrated by the following configuration:
@Bean public AnnotationSessionFactoryBean originalSessionFactory() { AnnotationSessionFactoryBean localSessionFactoryBean = new AnnotationSessionFactoryBean(); localSessionFactoryBean.setDataSource(dataSource()); localSessionFactoryBean.setPackagesToScan(packagesToScan()); localSessionFactoryBean.setHibernateProperties(additionalProperties()); return localSessionFactoryBean; } @Bean public SessionFactory sessionFactory(SessionFactory originalSessionFactory) { return HypersistenceHibernatePersistenceProvider.decorate( originalSessionFactory ); }
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-hibernate3-example
GitHub repository.
Decorating the Hibernate 3 SessionFactory with Spring XML configuration
If you’re using Hibernate 3, you can use the following XML configuration to decorate the Hibernate SessionFactory
:
<bean id="originalSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>${packages.to.scan}</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> </bean> <bean id="sessionFactory" class="io.hypersistence.optimizer.hibernate.decorator.HypersistenceHibernatePersistenceProvider" factory-method="decorate"> <constructor-arg ref="originalSessionFactory"/> </bean>
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-hibernate3-example
GitHub repository.
Decorating the Hibernate 3 JPA EntityManagerFactory programmatically with Spring Java-based configuration
To decorate the JPA EntityManagerFactory
, you just need to pass the EntityManagerFactory
reference to the decorate
method of the HypersistenceHibernatePersistenceProvider
class:
@Bean public EntityManagerFactory entityManagerFactory() { LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setPersistenceUnitName(persistenceUnitName()); entityManagerFactoryBean.setPersistenceProvider(new HibernatePersistence()); entityManagerFactoryBean.setDataSource(dataSource()); entityManagerFactoryBean.setPackagesToScan(packagesToScan()); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter); entityManagerFactoryBean.setJpaProperties(additionalProperties()); entityManagerFactoryBean.afterPropertiesSet(); return HypersistenceHibernatePersistenceProvider.decorate( entityManagerFactoryBean.getNativeEntityManagerFactory() ); }
To avoid creating two different beans of the EntityManagerFactory
type, that will prevent you from using the @PersistenceUnit
application without an explicit name qualifier, you can create the LocalContainerEntityManagerFactoryBean
and initialize it by calling afterPropertiesSet
prior to passing the resulting EntityManagerFactory
to the decorate
method.
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-jpa-hibernate3-example
GitHub repository.
Decorating the Hibernate 3 JPA EntityManagerFactory declaratively with Spring XML configuration
To decorate the JPA EntityManagerFactory
using the legacy XML configuration,
you just need to wrap the original EntityManagerFactory
as illustrated by the following examples.
<bean id="entityManagerFactory" class="io.hypersistence.optimizer.hibernate.decorator.HypersistenceHibernatePersistenceProvider" factory-method="decorate"> <constructor-arg> <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan"> <list> <value>${packages.to.scan}</value> </list> </property> <property name="jpaVendorAdapter" ref="jpaVendor"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> </bean> </constructor-arg> </bean>
Notice that we are just passing the LocalContainerEntityManagerFactoryBean
to the decorate
method of the
HypersistenceHibernatePersistenceProvider
utility in order to create the EntityManagerFactory
bean.
You can find a working example using the above configuration in the
hypersistence-optimizer-spring-jpa-hibernate3-example
GitHub repository.
Decorating the JPA EntityManagerFactory
declaratively
To decorate the JPA EntityManagerFactory
declaratively using the persistence.xml
configuration file, you need to use the HypersistenceHibernatePersistenceProvider
class, as illustrated by the provider
XML tag in the following example:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="persistenceUnit" transaction-type="JTA"> <provider>io.hypersistence.optimizer.hibernate.decorator.HypersistenceHibernatePersistenceProvider</provider> <jta-data-source>java:global/jdbc/default</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/> </properties> </persistence-unit> </persistence>
You can find a working example using the above configuration in the
hypersistence-optimizer-glassfish-hibernate4-example
GitHub repository.
Step 6: Instantiating HypersistenceOptimizer
Depending on your project environment, there are different ways you can instantiate the HypersistenceOptimizer
object, which is the main class of the Hypersistence Optimizer framework.
Spring Boot configuration
If you’re using Spring Boot, then you can instantiate the HypersistenceOptimizer
object like this:
@Configuration public class HypersistenceConfiguration { @Bean public HypersistenceOptimizer hypersistenceOptimizer( EntityManagerFactory entityManagerFactory) { return new HypersistenceOptimizer( new JpaConfig(entityManagerFactory) ); } }
Afterward, you can inject the HypersistenceOptimizer
dependency in your integration tests:
@RunWith(SpringRunner.class) @DataJpaTest public class ApplicationTest { @Autowired private HypersistenceOptimizer hypersistenceOptimizer; @Test public void test() { assertTrue(hypersistenceOptimizer.getEvents().isEmpty()); } }
The
hypersistence-optimizer-spring-boot-example
GitHub project demonstrates how you can use Hypersistence Optimizer in a Spring Boot project.
Spring and JPA configuration
If you’re using Hibernate via JPA, you can instantiate the HypersistenceOptimizer
object like this:
@Bean public HypersistenceOptimizer hypersistenceOptimizer( EntityManagerFactory entityManagerFactory) { return new HypersistenceOptimizer( new JpaConfig(entityManagerFactory) ); }
The
hypersistence-optimizer-spring-jpa-example
GitHub project demonstrates how you can use Hypersistence Optimizer in a Spring JPA project.
Spring and Hibernate configuration
If you’re using Hibernate via the native API, then you can instantiate the HypersistenceOptimizer
object like this:
@Bean public HypersistenceOptimizer hypersistenceOptimizer( SessionFactory sessionFactory) { return new HypersistenceOptimizer( new HibernateConfig(sessionFactory) ); }
The
hypersistence-optimizer-spring-hibernate-example
GitHub project demonstrates how you can use Hypersistence Optimizer in a Spring Hibernate project.
Java EE configuration
If you’re using Java EE, you can instantiate the hypersistenceOptimizer
object in an Arquillian Integration Test, as follows:
@PersistenceUnit private EntityManagerFactory entityManagerFactory; private HypersistenceOptimizer hypersistenceOptimizer; @Before public void init() { hypersistenceOptimizer = new HypersistenceOptimizer( new JpaConfig( getEntityManagerFactory() ) ); }
The
hypersistence-optimizer-glassfish-hibernate-example
GitHub repository demonstrates how you can use Hypersistence Optimizer in a Java EE project.
Grails configuration
If you’re using Grails, then you can get the reference to the underlying SessionFactory
and use it to build the HibernateConfig
instance.
With the HibernateConfig
object in place, you can instantiate the HypersistenceOptimizer
object, as illustrated by the following example:
class PetclinicService { def sessionFactory def hypersistenceOptimizer @PostConstruct void init() { hypersistenceOptimizer = new HypersistenceOptimizer( new HibernateConfig(sessionFactory) ) } ... }
Because the Grails DomainClassUnitTestMixin
uses the SimpleMapDatastore
, and not the HibernateDatastore
, you won’t be able to integrate Hypersistence Optimizer with tests that use the DomainClassUnitTestMixin
.
So, to see the Hypersistence Optimizer events, you should start the Grails Application
instead and check out the logs for the optimization events.
This GitHub repository demonstrates how you can use Hypersistence Optimizer in a Grails project.
Play Framework configuration
If you’re using Play Framework, you can get the reference to the default EntityManagerFactory
via reflection from the JPAApi
object reference.
Once you get the EntityManagerFactory
object reference, you can use it to build the JpaConfig
and instantiate the HypersistenceOptimizer
object, like this:
public class PostRepositoryImpl implements PostRepository { private final JPAApi jpaApi; private final DatabaseExecutionContext executionContext; private final HypersistenceOptimizer hypersistenceOptimizer; @Inject public PostRepositoryImpl( JPAApi jpaApi, DatabaseExecutionContext executionContext) { this.jpaApi = jpaApi; this.executionContext = executionContext; Map<String, EntityManagerFactory> emfs = ReflectionUtils.getFieldValue( jpaApi, "emfs" ); this.hypersistenceOptimizer = new HypersistenceOptimizer( new JpaConfig(emfs.get("default")) ); } //Code omitted for brevity }
Why not get the EntityManagerFactory from withTransaction?
Getting the
EntityManagerFactory
via reflection is the only we can get access to the decoratedSessionFactory
, which allows Hypersistence Optimizer to intercept queries or the Persistence Context actions.
While this is the idiomatic way of getting the EntityManagerFactory
when using Play Framework:
EntityManagerFactory emf = jpaApi.withTransaction(entityManager -> { return entityManager.getEntityManagerFactory(); });
Because the EntityManager
reference provided to the withTransaction
method is no longer associated with the decorated SessionFactory
, this approach is not recommended.
So, use the ReflectionUtils
class, that’s provided by Hypersistence Optimizer, to get access to the emfs
field of the DefaultJPAApi
object because that’s where the decorated SessionFactory
is stored by the Play Framework.
The
hypersistence-optimizer-play-example
GitHub project demonstrates how you can use Hypersistence Optimizer in a Play Framework project.
JDK and Hibernate requirements
The compatibility matrix between Hibernate, JPA and Java versions looks as follows:
Hibernate | JPA | Java |
---|---|---|
6.2 | 3.1 | Java 11 or newer |
6.1 | 3.1 | Java 11 or newer |
6.0 | 3.0 | Java 11 or newer |
5.6 | 2.2 | Java 8 or newer |
5.5 | 2.2 | Java 8 or newer |
5.4 | 2.2 | Java 8 or newer |
5.3 | 2.2 | Java 8 or above |
5.2 | 2.1 | Java 8 or newer |
5.1 | 2.1 | Java 8 or newer |
5.0 | 2.1 | Java 6 or newer |
4.3 | 2.1 | Java 6 or newer |
4.2 | 2.0 | Java 6 or newer |
4.1 | 2.0 | Java 6 or newer |
3.6 | 2.0 | Java 6 or newer |
3.5 | 2.0 | Java 6 or newer |
3.3 | 1.0 | Java 6 or newer |
Therefore, you need to make sure that you are using the proper Java version based on what Hibernate is compiled with. Hypersistence Optimizer simply follows the Hibernate minimum Java requirement. So, if you’re using Hibernate 5.0, you can use Java 1.6 and Hypersistence Optimizer will work just fine.
If your application is running on a Java EE application server (e.g., JBoss 5) that instruments all classes found on your current Java 6 or 7 classpath, you might want to use the
jre6
hypersistence-optimizer
dependency version, as previously explained.If you’re using an IBM JDK, you should also set the
com.ibm.crypto.provider.DoRSATypeChecking
JVM property tofalse
as, by default, the IBM JDK does not allow you to decrypt the license key using the provided public key.-Dcom.ibm.crypto.provider.DoRSATypeChecking=false
For more details, check out this StackOverflow thread.
Other than Hibernate, Hypersistence Optimizer does not require any other dependency. For logging, it can use either SLF4J, if you already configured it into your application or JBoss logging, which is required by Hibernate anyway.
Using an external Hypersistence Optimizer license file
Normally, you don’t need to specify any license file since Hypersistence Optimizer comes with an embedded license key. However, if you are using a managed environment (e.g., OSGI), which prevents loading the license file from the Hypersistence Optimizer jar, then you might want to set the license using an external URL:
new HypersistenceOptimizer( new JpaConfig(entityManagerFactory()) .setLicenseFileUrl(new URL("file:///path/to/license/file")) );
User Guide
And, that’s pretty much what you need in order to install Hypersistence Optimizer.
Now, you should proceed with the User Guide to see how you can configure and customize Hypersistence Optimizer.
Release Notes
You can check out the release notes using the following link.