쿼리 수행 중 Timeout이 발생할 경우에 아래 에러가 발생했다.
java.sql.SQLTimeoutException: The query has timed out.
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226) ~[mssql-jdbc-7.2.2.jre8.jar:?]
at com.microsoft.sqlserver.jdbc.SQLServerStatement.execute(SQLServerStatement.java:744) ~[mssql-jdbc-7.2.2.jre8.jar:?]
at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95) ~[HikariCP-3.3.1.jar:?]
at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-3.3.1.jar:?]
...
이 경우에는 DBTimeout으로 Exception만 발생하는 것이 아니라 현재 연결되어 있는 DBConnection을 close 하기 때문에 후에 트랜잭션 처리에 어려움을 겪게 된다.
dao1.insertData(DTO); --- first Insert
dao1.insertData2(DTO); --- second Insert
해당 코드처럼 한 개의 로직에서 두개의 DB처리(INSERT, UPDATE, DELETE)를 할 경우 1번 정상처리 --> 2번에서 SQLTimeoutException (DB Timeout) 이 발생하게 되면 개별트랜잭션 처리를 하지 않아도 1번 insert 한 데이터가 Rollback 되지 않고 자동 Commit 처리가 된다.
또 자동 Commit 처리가 된 후 별도의 트랜잭션을 처리 할 수 없도록 Connection을 끊어버리게 되는데 해당 문제를 해결하기 위해 Hikari Config 설정 클래스를 추가해야 한다.
import java.sql.SQLException;
import java.sql.SQLTimeoutException;
import com.zaxxer.hikari.SQLExceptionOverride;
public class HikariPreventQueryTimeoutEviction implements SQLExceptionOverride {
@java.lang.Override
public Override adjudicate(SQLException e) {
if(e instanceof SQLTimeoutException) {
return Override.DO_NOT_EVICT;
}
return null;
}
}
Hikari의 SQLExceptionOverride 클래스를 상속받아 SQLTimeoutException이 발생할 경우에만 Connection을 끊어주지 않도록 설정을 변경해 준다.
생성한 클래스를 데이터소스 생성시에 적용 할 수 있도록 DataSourceConfiguration
에 추가
spring:
datasoutce:
hikari:
exception-override-class-name: com.spring.web.config.HikariPreventQueryTimeoutEviction
# 생성한 SQLExceptionOverride 상속 클래스 추가
spring.datasource.hikari.exception-override-class-name=com.spring.web.config.HikariPreventQueryTimeoutEviction
# 생성한 SQLExceptionOverride 상속 클래스 추가
@Bean(name="dataSource")
@ConfigurationProperties(prefix="spring.datasource.oracle")
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setExceptionOverrideClassName(HikariPreventQueryTimeoutEviction.class.getName());
return dataSource;
}
많이 사용하는 yaml, properties, java 설정을 추가하는 방법들이다.
출처 - https://github.com/brettwooldridge/HikariCP/issues/1388