Use SQLExceptionTranslator bean if defined
This commit improves the auto-configuration of JdbcTemplate and HibernateJpaDialect so that an SQLExceptionTranslator bean is used if it is available. See gh-43511
This commit is contained in:
parent
276b888064
commit
86ef089d16
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,12 +18,14 @@ package org.springframework.boot.autoconfigure.jdbc;
|
|||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
|
||||
/**
|
||||
* Configuration for {@link JdbcTemplateConfiguration}.
|
||||
|
@ -36,7 +38,8 @@ class JdbcTemplateConfiguration {
|
|||
|
||||
@Bean
|
||||
@Primary
|
||||
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
|
||||
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties,
|
||||
ObjectProvider<SQLExceptionTranslator> sqlExceptionTranslator) {
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
JdbcProperties.Template template = properties.getTemplate();
|
||||
jdbcTemplate.setFetchSize(template.getFetchSize());
|
||||
|
@ -44,6 +47,7 @@ class JdbcTemplateConfiguration {
|
|||
if (template.getQueryTimeout() != null) {
|
||||
jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
|
||||
}
|
||||
sqlExceptionTranslator.ifUnique(jdbcTemplate::setExceptionTranslator);
|
||||
return jdbcTemplate;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
|
|||
import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.jndi.JndiLocatorDelegate;
|
||||
import org.springframework.orm.hibernate5.SpringBeanContainer;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
|
@ -95,6 +96,8 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
|
|||
|
||||
private final DataSourcePoolMetadataProvider poolMetadataProvider;
|
||||
|
||||
private final ObjectProvider<SQLExceptionTranslator> sqlExceptionTranslator;
|
||||
|
||||
private final List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers;
|
||||
|
||||
HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties,
|
||||
|
@ -104,11 +107,13 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
|
|||
ObjectProvider<SchemaManagementProvider> providers,
|
||||
ObjectProvider<PhysicalNamingStrategy> physicalNamingStrategy,
|
||||
ObjectProvider<ImplicitNamingStrategy> implicitNamingStrategy,
|
||||
ObjectProvider<SQLExceptionTranslator> sqlExceptionTranslator,
|
||||
ObjectProvider<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
|
||||
super(dataSource, jpaProperties, jtaTransactionManager);
|
||||
this.hibernateProperties = hibernateProperties;
|
||||
this.defaultDdlAutoProvider = new HibernateDefaultDdlAutoProvider(providers);
|
||||
this.poolMetadataProvider = new CompositeDataSourcePoolMetadataProvider(metadataProviders.getIfAvailable());
|
||||
this.sqlExceptionTranslator = sqlExceptionTranslator;
|
||||
this.hibernatePropertiesCustomizers = determineHibernatePropertiesCustomizers(
|
||||
physicalNamingStrategy.getIfAvailable(), implicitNamingStrategy.getIfAvailable(), beanFactory,
|
||||
hibernatePropertiesCustomizers.orderedStream().toList());
|
||||
|
@ -134,7 +139,9 @@ class HibernateJpaConfiguration extends JpaBaseConfiguration {
|
|||
|
||||
@Override
|
||||
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
|
||||
return new HibernateJpaVendorAdapter();
|
||||
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
|
||||
this.sqlExceptionTranslator.ifUnique(adapter.getJpaDialect()::setJdbcExceptionTranslator);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -34,6 +34,8 @@ import org.springframework.jdbc.core.JdbcOperations;
|
|||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -204,6 +206,31 @@ class JdbcTemplateAutoConfigurationTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConfigureJdbcTemplateWithSQLExceptionTranslatorIfPresent() {
|
||||
SQLStateSQLExceptionTranslator sqlExceptionTranslator = new SQLStateSQLExceptionTranslator();
|
||||
this.contextRunner.withBean(SQLExceptionTranslator.class, () -> sqlExceptionTranslator).run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcTemplate.class);
|
||||
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
|
||||
assertThat(jdbcTemplate.getExceptionTranslator()).isSameAs(sqlExceptionTranslator);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotConfigureJdbcTemplateWithSQLExceptionTranslatorIfNotUnique() {
|
||||
SQLStateSQLExceptionTranslator sqlExceptionTranslator1 = new SQLStateSQLExceptionTranslator();
|
||||
SQLStateSQLExceptionTranslator sqlExceptionTranslator2 = new SQLStateSQLExceptionTranslator();
|
||||
this.contextRunner
|
||||
.withBean("sqlExceptionTranslator1", SQLExceptionTranslator.class, () -> sqlExceptionTranslator1)
|
||||
.withBean("sqlExceptionTranslator2", SQLExceptionTranslator.class, () -> sqlExceptionTranslator2)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcTemplate.class);
|
||||
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
|
||||
assertThat(jdbcTemplate.getExceptionTranslator()).isNotSameAs(sqlExceptionTranslator1)
|
||||
.isNotSameAs(sqlExceptionTranslator2);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomConfiguration {
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
|
@ -169,6 +171,24 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes
|
|||
(adapter) -> assertThat(adapter.getJpaPropertyMap()).doesNotContainKeys("hibernate.dialect")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConfigureHibernateJpaDialectWithSqlExceptionTranslatorIfPresent() {
|
||||
SQLStateSQLExceptionTranslator sqlExceptionTranslator = new SQLStateSQLExceptionTranslator();
|
||||
contextRunner().withBean(SQLStateSQLExceptionTranslator.class, () -> sqlExceptionTranslator)
|
||||
.run(assertJpaVendorAdapter((adapter) -> assertThat(adapter.getJpaDialect())
|
||||
.hasFieldOrPropertyWithValue("jdbcExceptionTranslator", sqlExceptionTranslator)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotConfigureHibernateJpaDialectWithSqlExceptionTranslatorIfNotUnique() {
|
||||
SQLStateSQLExceptionTranslator sqlExceptionTranslator1 = new SQLStateSQLExceptionTranslator();
|
||||
SQLStateSQLExceptionTranslator sqlExceptionTranslator2 = new SQLStateSQLExceptionTranslator();
|
||||
contextRunner().withBean("sqlExceptionTranslator1", SQLExceptionTranslator.class, () -> sqlExceptionTranslator1)
|
||||
.withBean("sqlExceptionTranslator2", SQLExceptionTranslator.class, () -> sqlExceptionTranslator2)
|
||||
.run(assertJpaVendorAdapter((adapter) -> assertThat(adapter.getJpaDialect())
|
||||
.hasFieldOrPropertyWithValue("jdbcExceptionTranslator", null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hibernateDialectIsSetWhenDatabaseIsSet() {
|
||||
contextRunner().withPropertyValues("spring.jpa.database=H2")
|
||||
|
|
Loading…
Reference in New Issue