HikariCP Customization Tips

Hello everyone! In this article I will try to tell you about the interesting subtleties of working with HikariPool. We will analyze the features of the settings HikariCP For Java applicationswe'll discuss potential problems that can arise when working with connection pooling, and look at how to effectively work with two databases at the same time.

Made by DALLE

Made by DALLE

What is HikariPool?

HikariPool — is a super-fast, lightweight database connection pool designed specifically for Java applications. His goal — ensure the most efficient use of database resources and minimize delays in query execution. HikariCPas it is also called, is renowned for its performance and stability, making it one of the most popular connection pools in the Java world.

Why is HikariCP so popular? Firstlyit is minimalistic, yet incredibly powerful. Unlike other connection pools, HikariCP is not overloaded with features that you will most likely never use. Instead, it focuses on what matters most – speed and reliability. HikariCP Streamlines the process of creating, managing, and terminating connections, allowing your application to run faster and more efficiently.

Besides, HikariCP easy to configure. With a variety of configuration parameters, you can tailor the connection pool to your needs, ensuring a balance between performance and stability. For example, you can manage the maximum number of active connections, set wait timeouts, and control the lifetime of connections, which is especially important when working with two databases at the same time.

Setting up HikariCP

When working with HikariPool It is important to understand that proper configuration of this tool can significantly affect the performance of your Java application. Let's look at the main parameters that should be configured:

hikari:
  idle-timeout: 120000
  minimum-idle: 2
  maximum-pool-size: 30

1. idle timeout

Parameter idle-timeout specifies how many milliseconds an idle connection can remain in the pool before it is closed. The example specifies 120000which is equivalent to 2 minutes. This means that if the connection is not used for 2 minutes, it will be automatically closed and released.

2. minimum-idle

Parameter minimum-idle specifies the minimum number of free (inactive) connections that the pool will always support. In our example, this value is 2. This means that the pool will always try to maintain at least 2 free connections so that they are immediately available for use when needed.

3. maximum-pool-size

Parameter maximum-pool-size specifies the maximum number of connections that can be active in the pool at the same time. In this example, this value is 30. This parameter should be carefully tuned depending on your application requirements and database capabilities. For example, if you are using PostgreSQL, where the maximum number of connections is set to 500, the value maximum-pool-size should be configured to stay within this limit, taking into account other applications using the same database.

Configuring HikariPool depending on your system

It is important to understand that the values ​​of these parameters need to be set independently, based on the characteristics of your system and the requirements of your application. For example, if your application has a high load, you may need to increase maximum-pool-sizeto ensure that there are enough connections. However, you should not set it too high, so as not to exhaust the connection limits of the database and not to create risks for other applications that may use the same resources.

Possible problems with incorrect HikariPool configuration

If you don't configure HikariPool properly, you may encounter a number of problems that can seriously affect the performance of your application. One of the main problems is the uncontrolled growth of the number of connections. If maximum-pool-size If this is not configured, or is set too high, the number of connections may begin to grow indefinitely without being closed in a timely manner. This can lead to database resource exhaustion, failures in other applications, and overall performance degradation.

Also, if you do not configure the settings idle-timeout And minimum-idleyou risk running into a situation where the connection pool is full of unused but not closed connections, which will also waste resources and degrade application responsiveness.

Setting up connections for multiple databases

1. Defining database connection attributes in application.yml

The first step in setting up multiple databases in Spring is to define connection attributes for each database in the configuration file. application.ymlHere we will specify the parameters for two databases: Zangetsu (PostgreSQL) and Zabimaru (Oracle).

These parameters include the connection URL (jdbcUrl), username (username), password (password), as well as connection pool settings via HikariCP.

Configuration example in application.yml:

spring:
  zangetsu:
    datasource:
      password: ZangetsuPass123!
      jdbcUrl: jdbc:postgresql://10.0.0.1:5432/zangetsu_db?currentSchema=zangetsu_schema
      username: zangetsu_user
      hikari:
        idle-timeout: 120000
        minimum-idle: 2
        maximum-pool-size: 15
      driver-class-name: org.postgresql.Driver
  zabimaru:
    datasource:
      jdbcUrl: "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.0.0.2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=zabimaru_service)))"
      username: zabimaru_user
      password: ZabimaruPass#456
      driver-class-name: oracle.jdbc.OracleDriver
      schema: zabimaru_schema

2. Create configuration classes for each database

After we have defined the connection parameters in application.ymlthe next step is to create configuration classes for each database. In these classes we will create beans to connect to the database, EntityManager, TransactionManager And NamedParameterJdbcTemplate.

Each configuration class will be responsible for one of the databases. It is important to give unique names to the methods to avoid conflicts when using multiple databases.

You should also pay attention to the correct placement. Entity and repositories. All Entity classes must be in the appropriate package specified in the configuration so that Spring can configure it correctly. EntityManagerFactory. Repositories must be in their own packages so that Spring can discover them and associate them with the correct one. EntityManagerFactory.

Configuration for Zangetsu Database (PostgreSQL)

In this class we create the configuration for the Zangetsu database, which uses PostgreSQL. We define beans for DataSource, EntityManagerFactory, TransactionManager And NamedParameterJdbcTemplate.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "com.example.zangetsu.repository",
        entityManagerFactoryRef = "zangetsuEntityManagerFactory",
        transactionManagerRef = "zangetsuTransactionManager"
)
public class ZangetsuDatabaseConfig {

    @Bean(name = "zangetsuDataSource")
    @ConfigurationProperties(prefix = "spring.zangetsu.datasource.hikari")
    public DataSource zangetsuDataSource() {
        return dataSourceProperties().initializeDataSourceBuilder()
                .type(HikariDataSource.class).build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.omni.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(name = "zangetsuEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean zangetsuEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("zangetsuDataSource") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.zangetsu.entity")
                .persistenceUnit("zangetsu")
                .build();
    }

    @Bean(name = "zangetsuTransactionManager")
    public PlatformTransactionManager zangetsuTransactionManager(@Qualifier("zangetsuEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean
    @Qualifier("zangetsuNamedParamJdbcTemplate")
    public NamedParameterJdbcTemplate zangetsuNamedParamJdbcTemplate(@Qualifier("zangetsuDataSource") DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

Configuration for Zabimaru Database (Oracle)

This class is responsible for the configuration for the Zabimaru database, which uses Oracle. We create similar beans for connecting to the database, but with unique names for each method.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "com.example.zabimaru.repository",
        entityManagerFactoryRef = "zabimaruEntityManagerFactory",
        transactionManagerRef = "zabimaruTransactionManager"
)
public class ZabimaruDatabaseConfig {

    @Bean(name = "zabimaruDataSource")
    @ConfigurationProperties(prefix = "spring.zabimaru.datasource")
    public DataSource zabimaruDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "zabimaruEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean zabimaruEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("zabimaruDataSource") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.zabimaru.entity")
                .persistenceUnit("zabimaru")
                .build();
    }

    @Bean(name = "zabimaruTransactionManager")
    public PlatformTransactionManager zabimaruTransactionManager(@Qualifier("zabimaruEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean
    @Qualifier("zabimaruNamedParamJdbcTemplate")
    public NamedParameterJdbcTemplate zabimaruNamedParamJdbcTemplate(@Qualifier("zabimaruDataSource") DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

3. Setting up migration with Flyway for each database

The final step is to set up migrations for each database. We will create configuration classes for Flyway where we explicitly specify the path to migrations for each database. This is important to separate migrations and ensure that each database schema is updated correctly.

Flyway Configuration for Zangetsu Database

In this class, we configure Flyway migrations for the Zangetsu database. This specifies the path to migrations specific to this database.

@Configuration
public class ZangetsuFlywayConfig {

    @Bean
    public Flyway zangetsuFlyway(@Qualifier("zangetsuDataSource") DataSource dataSource) {
        Flyway flyway = Flyway.configure()
                .dataSource(dataSource)
                .locations("classpath:db/migration/zangetsu")
                .load();
        flyway.migrate();
        return flyway;
    }
}

Flyway Configuration for Zabimaru Database

Similarly, for the Zabimaru database, we set up a separate class for Flyway migrations. The path to migrations for this database is also specified here.

@Configuration
public class ZabimaruFlywayConfig {

    @Bean
    public Flyway zabimaruFlyway(@Qualifier("zabimaruDataSource") DataSource dataSource) {
        Flyway flyway = Flyway.configure()
                .dataSource(dataSource)
                .locations("classpath:db/migration/zabimaru")
                .load();
        flyway.migrate();
        return flyway;
    }
}

Similar Posts

Leave a Reply

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