My project includes the combination of Spring Boot + Hibernate + Postgresql. Since the project started I thought adding @Transactional to the method will automatically triggered a rollback when a RunTimeException is thrown, but it seems that I was wrong. Here's the the application properties.
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
spring.jpa.properties.hibernate.default_schema=sbs
# HIKARI CONNECTION POOL
spring.datasource.hikari.pool-name=SBS_Datasource
#spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=3
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.idle-timeout=10000
spring.datasource.hikari.max-lifetime=600000
spring.datasource.hikari.connection-test-query=select 1
spring.datasource.hikari.connection-init-sql=select 1
spring.datasource.hikari.isolate-internal-queries=true
spring.datasource.hikari.allow-pool-suspension=true
spring.datasource.hikari.register-mbeans=true
As you can see, the auto-commit
has been disabled, dialect is set to PostgreSQLDialect
and we're using hikari pool.
The situation is: this happens at start-up phase of the application. We want to load data from csv and persist into the database when the application is starting up. Here are the components:
@ConditionalOnProperty(
value = "sbs.api.master-data.enable-loader",
havingValue = "true"
)
@Slf4j
public class MasterDataLoader {
...
@PostConstruct
public void loadMasterData() {
log.info("***MasterDataLoader STARTS");
this.loadCountryCodes();
this.loadZipCities();
log.info("***MasterDataLoader ENDS");
}
private void loadCountryCodes() {
log.info("***Loading country codes from {}", this.countryCodeFilePath);
try {
List<CSVCountry> csvCountries = this.countryLoader.read(countryCodeFilePath);
this.countryLoader.save(csvCountries);
log.info("*** length " + csvCountries.size());
} catch (Exception e) {
log.warn("Exception while loading country code {}", e);
}
}
...
}
Code that has @Transaction inside countryLoadder
...
@Transactional
void save(List<CSVCountry> csvCountries) {
dossierRepository.save(new DossierEntity());
throw new NullPointerException();
}
}
...
The actual code is more complex than this but since I saw it didn't work so I decided to go with the simplest possible example.
I expected the created dossier would be removed because of @Transactional, but it wasn't.
Please help to tell what's wrong with the code or there is a problem with the technology stack (Spring + Hikari + PostgreSQL).
SOLUTION:
- Check this out: @Transactional on @PostConstruct method