I'm encountering an issue with Spring's JdbcClient where it seems to be creating an excessive number of sessions in my Oracle database. This behavior is leading to unexpected resource consumption and potential performance problems. I'm seeking assistance in understanding and resolving this issue.
Problem Description:
- Framework/Tools Used: I'm using Spring Boot with the JdbcClient for database interactions.
- Database: Oracle Database
- Observation: The application appears to be creating a large number of database sessions reach 4k session, which is impacting performance, for each execution of JdbcClient create database session.
Here's a snippet of my application
@Autowired
private JdbcClient jdbcClient;
jdbcClient.sql("query")
.param("id", id)
.query(String.class)
.stream().findFirst().orElseGet(() -> "")
while I'm using DriverManagerDataSource to connect to oracle database
Environment Information:
Spring Boot Version: 3.2.1 Oracle Database Version: 19c
when I'm using DriverManagerDataSource JdbcClient for each time called by client it will create session when i try to change data source from DriverManagerDataSource to HikariCP and setting connection pool that open sessions in database when application start but when i call end point that use JdbcClient first request get succeeded but any other request getting error and doesn't open too many sessions
error
Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30006ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:696)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:181)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:146)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:100)
at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:160)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:118)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:81)
... 109 more
what i see on database
sessions info
i think the database are waiting from JdbcClient to end connection but there is problem with it
more details..
main class
@EnableConfigurationProperties(RsaKeyProperties.class)
@SpringBootApplication
@EnableAutoConfiguration
@EnableEncryptableProperties
@EnableAsync
@EnableScheduling
@EnableCaching
@PropertySource(name = "EncryptedProperties", value = "classpath:database.properties")
public class Application
service class
@Service
public class InfoService {
@Autowired
private JdbcClient jdbcClient;
public SponsorInformation getInformation(String token, PhoneType phoneType) {
String id = tokenService.decodeToken(token.substring(7)).getSubject();
return jdbcClient.sql("query")
.param("id", id)
.query(String.class)
.stream().findFirst().orElseGet(() -> "");
}
app config class ( with hikari also try with DriverManagerDataSource )
@Configuration
@PropertySource("classpath:database.properties")
public class AppConfig {
@Autowired
Environment environment;
@Value("${url}")
private String URL;
@Value("${dbuser}")
private String USER;
@Value("${driver}")
private String DRIVER;
@Value("${dbpassword}")
private String PASSWORD;
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(URL);
config.setUsername(USER);
config.setPassword(PASSWORD);
config.setDriverClassName(DRIVER);
return new HikariDataSource(config);
}
}
application.properties
spring.datasource.hikari.connectionTimeout=60000
spring.datasource.hikari.idleTimeout=-1
spring.datasource.hikari.maxLifetime=-1
spring.datasource.hibernate.connection.characterEncoding=UTF-8
spring.mvc.charset=UTF-8
spring.datasource.oracleucp.min-pool-size=10
spring.datasource.oracleucp.max-pool-size=405
spring.datasource.hikari.maximum-pool-size =105
spring.datasource.hikari.minimum-idle =16
jasypt.encryptor.pool-size=20
database.properties
driver=oracle.jdbc.OracleDriver
url= jdbc:oracle:thin:@ip:port/sid?useUnicode=yes&characterEncoding=UTF-8
dbuser= [database_user]
dbpassword=[encrypted_database_password]

You are using the
stream()method from theJdbcClient. Now if you read the documentation that method comes with one caveat:If you don't close it it will keep the underlying
ResultSetand with that theStatementandConnectionopen. Modify your code to something like this.This will close the
Streamafter use and free the blocked resources.