Hypersistence Optimizer Installation Guide

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 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.2.0-pack.zip

After unzipping the project package, you will get the following file structure:

creating: hypersistence-optimizer-2.2.0/
   creating: hypersistence-optimizer-2.2.0/lib/
  inflating: hypersistence-optimizer-2.2.0/lib/hypersistence-optimizer-2.2.0-javadoc.jar
  inflating: hypersistence-optimizer-2.2.0/lib/hypersistence-optimizer-2.2.0-sources.jar
  inflating: hypersistence-optimizer-2.2.0/lib/hypersistence-optimizer-2.2.0.jar
  inflating: hypersistence-optimizer-2.2.0/lib/hypersistence-optimizer-2.2.0-jre6-javadoc.jar
  inflating: hypersistence-optimizer-2.2.0/lib/hypersistence-optimizer-2.2.0-jre6-sources.jar
  inflating: hypersistence-optimizer-2.2.0/lib/hypersistence-optimizer-2.2.0-jre6.jar
   creating: hypersistence-optimizer-2.2.0/configs/
   creating: hypersistence-optimizer-2.2.0/configs/META-INF/
   creating: hypersistence-optimizer-2.2.0/configs/META-INF/services/
  inflating: hypersistence-optimizer-2.2.0/configs/META-INF/services/org.hibernate.boot.spi.SessionFactoryBuilderFactory
   creating: hypersistence-optimizer-2.2.0/docs/
   creating: hypersistence-optimizer-2.2.0/docs/html/
   creating: hypersistence-optimizer-2.2.0/docs/pdf/
  inflating: hypersistence-optimizer-2.2.0/docs/html/asciidoctor.css
  inflating: hypersistence-optimizer-2.2.0/docs/html/coderay-asciidoctor.css
  inflating: hypersistence-optimizer-2.2.0/docs/pdf/InstallationGuide.pdf
  inflating: hypersistence-optimizer-2.2.0/docs/html/InstallationGuide.html
  inflating: hypersistence-optimizer-2.2.0/docs/html/UserGuide.html
  inflating: hypersistence-optimizer-2.2.0/docs/pdf/UserGuide.pdf
  inflating: hypersistence-optimizer-2.2.0/changelog.txt
  inflating: hypersistence-optimizer-2.2.0/LICENSE.txt
  inflating: hypersistence-optimizer-2.2.0/archiva-deploy.bat
  inflating: hypersistence-optimizer-2.2.0/archiva-deploy.sh
  inflating: hypersistence-optimizer-2.2.0/maven-install.bat
  inflating: hypersistence-optimizer-2.2.0/maven-install.sh
  inflating: hypersistence-optimizer-2.2.0/README.txt

The package contains the following resources:

  • the lib folder contains the main jar file, as well as the JavaDoc and the Java sources
  • the configs folder contains a Java service loader configuration file that is going to be explained in the next steps
  • 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

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 to your local repository.

If you have a group license and want to share it with your team, then you should use a Maven Artifact repository, like Apache Archiva or JFrog Artifactory.

Installing the Maven dependency on Apache Archiva

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:

> archive install
> archive start

After running these commands, Archiva will start a web application, which, by default, can be accessed at the http://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 ommitted for vrevity -->
    
    <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 ommitted for vrevity -->
    
</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 Archive 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 ommitted for vrevity -->

    <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 ommitted for vrevity -->
    
    <properties>
        <archiva-repository-id>archiva.internal</archiva-repository-id>
        <archiva-repository-url>http://localhost:8080/repository/internal/</archiva-repository-url>
        
        <!-- Other properties are ommitted for vrevity -->
    </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 Maven dependency to your project

Now, you need to add the hypersistence-optimizer dependency to your project.

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 which you need to declare in the properties tag of your pom.xml configuration file, like this:

<properties>
    ...
    <hypersistence-optimizer.version>2.2.0</hypersistence-optimizer.version>
</properties>

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.2.0'
}

Java 6 and 7

If your application is running on Java 6 or 7, you should use the {project-version}-jre6 dependency version.

Therefore, for Maven, the version XML tag of the hypersistence-optimizer dependency must be set to the value of {hypersistence-optimizer.-version}-jre6, like this:

<dependency>
    <groupId>io.hypersistence</groupId>
    <artifactId>hypersistence-optimizer</artifactId>
    <version>2.2.0-jre6</version>
</dependency>

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 the Console 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 automatically (requires Hibernate 5)

If you’re using Hibernate 5, you can easily substitute the currently configured Hibernate SessionFactory (even when using JPA with Hibernate), via the org.hibernate.boot.spi.SessionFactoryBuilderFactory service loader mechanism.

The Hypersistence Optimizer package contains a configs/META-INF folder that looks as follows:

> tree hypersistence-optimizer-2.2.0-pack
├── ...
├── configs
│   └── META-INF
│       └── services
│           └── org.hibernate.boot.spi.SessionFactoryBuilderFactory
└── ...

In order to decorate the Hibernate SessionFactory, you need to copy the entire META-INF folder to your current project src/test/resources folder.

The reason why we want the META-INF folder to be copied to the src/test/resources is that we are interested in decorating the Hibernate SessionFactory for the development and testing environments only.

Hypersistence Optimizer aims to find issues prior to deploying the application into production, and, since SessionFactory instrumentation can add a slight overhead, it’s better off using Hypersistence Optimizer in your pre-production environments.

Once you copy the META-INF folder to your project src/test/resources folder, you should have the following META-INF/services/org.hibernate.boot.spi.SessionFactoryBuilderFactory file:

> tree src/test/resources
├── ...
└── META-INF
    └── services
        └── org.hibernate.boot.spi.SessionFactoryBuilderFactory

Decorating the Persistence Unit manually (for 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 manually 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 manually 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 manually using Spring and Hibernate 3 declaratively

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.

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 got 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 decorated SessionFactory, 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
5.4 2.2 Java 8 or above
5.3 2.2 Java 8 or above
5.2 2.1 Java 8 or above
5.1 2.1
  • Java 8 from 5.1.17 onwards
  • Java 7 from 5.1.14
  • Java 6 or above until 5.1.3
5.0 2.1 Java 6 or above
4.3 2.1 Java 6 or above
4.2 2.0 Java 6 or above
4.1 2.0 Java 6 or above
3.6 2.0 Java 6 or above
3.5 2.0 Java 6 or above
3.3 1.0 Java 6 or above

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 to false 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.