Reuse JdbcTemplate in NamedParameterJdbcTemplate

This commit makes sure to reuse an existing or auto-configured
`JdbcTemplate` when auto-configuring a `NamedParameterJdbcTemplate`.

This ensures that whatever customizations have been applied on the
`JdbcTemplate` are properly shared.

Closes gh-4945
This commit is contained in:
Stephane Nicoll 2017-06-01 10:08:13 +02:00
parent 42762a66b8
commit ad85902880
3 changed files with 85 additions and 16 deletions

View File

@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
@ -47,24 +48,36 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class JdbcTemplateAutoConfiguration {
private final DataSource dataSource;
@Configuration
static class JdbcTemplateConfiguration {
private final DataSource dataSource;
JdbcTemplateConfiguration(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
@Primary
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}
public JdbcTemplateAutoConfiguration(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
@Primary
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}
@Configuration
@Import(JdbcTemplateConfiguration.class)
static class NamedParameterJdbcTemplateConfiguration {
@Bean
@Primary
@ConditionalOnSingleCandidate(JdbcTemplate.class)
@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) {
return new NamedParameterJdbcTemplate(jdbcTemplate);
}
@Bean
@Primary
@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
return new NamedParameterJdbcTemplate(this.dataSource);
}
}

View File

@ -28,12 +28,14 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
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.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link JdbcTemplateAutoConfiguration}.
@ -56,7 +58,7 @@ public class JdbcTemplateAutoConfigurationTests {
@Test
public void testJdbcTemplateExists() {
load();
assertThat(this.context.getBeansOfType(JdbcTemplate.class)).hasSize(1);
assertThat(this.context.getBeansOfType(JdbcOperations.class)).hasSize(1);
JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class);
assertThat(jdbcTemplate.getDataSource()).isEqualTo(
this.context.getBean(DataSource.class));
@ -65,7 +67,7 @@ public class JdbcTemplateAutoConfigurationTests {
@Test
public void testJdbcTemplateExistsWithCustomDataSource() {
load(TestDataSourceConfiguration.class);
assertThat(this.context.getBeansOfType(JdbcTemplate.class)).hasSize(1);
assertThat(this.context.getBeansOfType(JdbcOperations.class)).hasSize(1);
JdbcTemplate jdbcTemplate = this.context.getBean(JdbcTemplate.class);
assertThat(jdbcTemplate).isNotNull();
assertThat(jdbcTemplate.getDataSource()).isEqualTo(
@ -77,6 +79,10 @@ public class JdbcTemplateAutoConfigurationTests {
load();
assertThat(this.context.getBeansOfType(NamedParameterJdbcOperations.class))
.hasSize(1);
NamedParameterJdbcTemplate namedParameterJdbcTemplate = this.context.getBean(
NamedParameterJdbcTemplate.class);
assertThat(namedParameterJdbcTemplate.getJdbcOperations()).isEqualTo(
this.context.getBean(JdbcOperations.class));
}
@Test
@ -87,6 +93,13 @@ public class JdbcTemplateAutoConfigurationTests {
.isEmpty();
}
@Test
public void testMultiJdbcTemplate() {
load(MultiJdbcTemplateConfiguration.class);
assertThat(this.context.getBeansOfType(NamedParameterJdbcOperations.class))
.isEmpty();
}
@Test
public void testMultiDataSourceUsingPrimary() {
load(MultiDataSourceUsingPrimaryConfiguration.class);
@ -97,6 +110,15 @@ public class JdbcTemplateAutoConfigurationTests {
.isEqualTo(this.context.getBean("test1DataSource"));
}
@Test
public void testMultiJdbcTemplateUsingPrimary() {
load(MultiJdbcTemplateUsingPrimaryConfiguration.class);
assertThat(this.context.getBeansOfType(NamedParameterJdbcOperations.class))
.hasSize(1);
assertThat(this.context.getBean(NamedParameterJdbcTemplate.class)
.getJdbcOperations()).isEqualTo(this.context.getBean("test1Template"));
}
@Test
public void testExistingCustomJdbcTemplate() {
load(CustomConfiguration.class);
@ -159,4 +181,35 @@ public class JdbcTemplateAutoConfigurationTests {
}
@Configuration
static class MultiJdbcTemplateConfiguration {
@Bean
public JdbcTemplate test1Template() {
return mock(JdbcTemplate.class);
}
@Bean
public JdbcTemplate test2Template() {
return mock(JdbcTemplate.class);
}
}
@Configuration
static class MultiJdbcTemplateUsingPrimaryConfiguration {
@Bean
@Primary
public JdbcTemplate test1Template() {
return mock(JdbcTemplate.class);
}
@Bean
public JdbcTemplate test2Template() {
return mock(JdbcTemplate.class);
}
}
}

View File

@ -2932,6 +2932,9 @@ you can `@Autowire` them directly into your own beans:
}
----
TIP: The `NamedParameterJdbcTemplate` reuses the same `JdbcTemplate` instance behind the
scene. If more than one `JdbcTemplate` is defined and no primary candidate exists, the
`NamedParameterJdbcTemplate` is not auto-configured.
[[boot-features-jpa-and-spring-data]]