Performance tuning in spring boot

Posted By :Harshit Verma |26th November 2019

When developing a Spring Boot application is easy, tuning the performance of a Spring Boot application is a more challenging task, as, not only it requires to understand how the Spring framework works behind scenes, but you have to know is the best way to use underlying data access framework, like Hibernate for instance. we are going to switch underlying database from in-memory HSQLDB to MySQL and run Hypersistence Optimizer to generate the performance tuning report for JPA and Hibernate data access layer in the context of MySQL database.

By default, Spring Boot uses the HSQLDB, but while this in-memory database is used extensively for the testing, in the production environment, you are more likely to use the database like MySQL or PostgreSQL.Luckily, Spring Boot offers the MySQL configuration and the Spring profile, which we can use as a starting point for the analysis.

Switching tests to using a MySQL profile
First of all, we need to use a @ActiveProfiles annotation to activate a mysql Spring profile.

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("mysql")
public class Tests {
 
    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;
 
    @Autowired
    private VetRepository vets;
 
    @Before
    public void init() {
        new HypersistenceOptimizer(
            new JpaConfig(entityManagerFactory)
        ).init();
    }
 
    @Test
    public void testFindAll() throws Exception {
        vets.findAll();
        vets.findAll();
    }
}

After activating a MySQL Spring profile, Spring Boot is going to use an application-MySQL. properties configuration file to override settings from a default application.properties settings file.

In our case, the only change that was needed in an application-MySQL. the properties configuration file was to change the database connection credentials:

database=mysql
 
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=mysql
spring.datasource.password=admin

Running Hypersistence Optimizer

As you can see in a Tests class, running Hypersitence Optimizer is very easy, as you just have to pass an EntityManagerFactory instance to a HypersistenceOptimizer object constructor, and call a init method.

By providing the MySQL-specific orm.xml JPA configuration file that overrides a base class entity identifier strategy, we can switch to using IDENTITY when using MySQL.

So, we are going to create an orm.xml file that's going to be deployed by a MySQL profile in the META-INF folder in the application jar file.

The orm.xml configuration file looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
 
<entity-mappings
    xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"
    version="2.2">
 
    <mapped-superclass
        class="org.springframework.samples.petclinic.model.BaseEntity">
        <attributes>
            <id name="id">
                <generated-value strategy="IDENTITY"/>
            </id>
        </attributes>
    </mapped-superclass>
 
</entity-mappings>

Now, when rerunning test case, Hypersistence Optimizer will generate the following report:

Hypersistence Optimizer : MAJOR - PostInsertGeneratorEvent -
The [id] identifier attribute in the [org.springframework.samples.test] entity uses a [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts.
/#PostInsertGeneratorEvent
 
Hypersistence Optimizer : MAJOR - PostInsertGeneratorEvent -
The [id] identifier attribute in the [org.springframework.samples.test] entity uses a [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts.

But since we don't really have an option for a PostInsertGeneratorEvent when using MySQL, we can simply choose to ignore this event in our case.

Filtering Hyperstistence Optimizer events

Hypersitence Optimizer is very flexible. You can customize how events are handled, whether you want them to be logged or collected to  List, and you can choose to filter events as well.

To filter out a PostInsertGeneratorEvent, you need to configure Hyperstistence Optimizer[] like this:

@Before
public void init() {
    new HypersistenceOptimizer(
        new JpaConfig(entityManagerFactory)
            .setEventFilter(
                event -> !(event instanceof PostInsertGeneratorEvent)
            )
    ).init();
}

Now, when rerunning  test case, Hypersistence Optimizer will prevent a PostInsertGeneratorEvent from being included in the report:

Hypersistence Optimizer : MAJOR - DialectVersionEvent -
Your application is using a [org.hibernate.dialect.MySQL5Dialect] Hibernate-specific Dialect. Consider using a [org.hibernate.dialect.MySQL57Dialect] instead as it's closer to your current database server version [MySQL 8.0].

/#DialectVersionEvent
DialectVersionEvent

The DialectVersionEvent is generated because the default configured Hibernate dialect is MySQL57Dialect while an application is running against MySQL 8.

So, we just have to include the MySQL8Dialect in a Spring Boot application-MySQL. properties configuration file:

database=mysql
 
spring.datasource.url=jdbc:mysql://localhost/petclinic
spring.datasource.username=mysql
spring.datasource.password=admin
 
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect

Hypersistence Optimizer is a very powerful tool that can help you detect JPA and Hibernate performance issues long before they hit a production system. And, one of its greatest advantages is that it can do all these checks on commit, so you will no longer overlook the JPA or Hibernate performance-related improvement because of the very tight development schedule.

 


About Author

Harshit Verma

Harshit is a bright Web Developer with expertise in Java and Spring framework and ORM tools Hibernate.

Request For Proposal

[contact-form-7 404 "Not Found"]

Ready to innovate ? Let's get in touch

Chat With Us