From a28a2cd5173425026be182328d2c6f9d313ad0f5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 28 Oct 2025 10:32:00 +0100 Subject: [PATCH] Introduce `JdbcConfiguration` and extract factory methods used from `AbstractJdbcConfiguration`. Closes: #2165 Original pull request: #2166 --- .../config/AbstractJdbcConfiguration.java | 83 ++------- .../repository/config/JdbcConfiguration.java | 168 ++++++++++++++++++ .../config/MyBatisJdbcConfiguration.java | 5 +- ...ractJdbcConfigurationIntegrationTests.java | 7 +- ...atisJdbcConfigurationIntegrationTests.java | 6 +- .../ROOT/pages/jdbc/getting-started.adoc | 12 +- .../modules/ROOT/pages/jdbc/mapping.adoc | 4 +- .../ROOT/pages/r2dbc/getting-started.adoc | 8 +- .../modules/ROOT/pages/r2dbc/mapping.adoc | 2 +- 9 files changed, 203 insertions(+), 92 deletions(-) create mode 100644 spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java index bdc1f3c1f..fa9b00e95 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java @@ -15,7 +15,6 @@ */ package org.springframework.data.jdbc.repository.config; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -23,8 +22,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -32,34 +29,23 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.convert.CustomConversions; import org.springframework.data.jdbc.core.JdbcAggregateOperations; import org.springframework.data.jdbc.core.JdbcAggregateTemplate; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; -import org.springframework.data.jdbc.core.convert.DataAccessStrategyFactory; -import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory; import org.springframework.data.jdbc.core.convert.IdGeneratingEntityCallback; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; -import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration; import org.springframework.data.jdbc.core.convert.RelationResolver; import org.springframework.data.jdbc.core.dialect.DialectResolver; -import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns; import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; -import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes; -import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.relational.RelationalManagedTypes; import org.springframework.data.relational.core.conversion.RelationalConverter; import org.springframework.data.relational.core.dialect.Dialect; -import org.springframework.data.relational.core.mapping.DefaultNamingStrategy; import org.springframework.data.relational.core.mapping.NamingStrategy; import org.springframework.data.relational.core.mapping.Table; -import org.springframework.data.util.TypeScanner; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; -import org.springframework.util.StringUtils; /** * Beans that must be registered for Spring Data JDBC to work. @@ -77,8 +63,6 @@ import org.springframework.util.StringUtils; @Configuration(proxyBeanMethods = false) public class AbstractJdbcConfiguration implements ApplicationContextAware { - private static final Log LOG = LogFactory.getLog(AbstractJdbcConfiguration.class); - @SuppressWarnings("NullAway.Init") private ApplicationContext applicationContext; private QueryMappingConfiguration queryMappingConfiguration = QueryMappingConfiguration.EMPTY; @@ -96,7 +80,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { protected Collection getMappingBasePackages() { Package mappingBasePackage = getClass().getPackage(); - return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName()); + return mappingBasePackage == null ? List.of() : List.of(mappingBasePackage.getName()); } /** @@ -124,13 +108,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { @Bean public JdbcMappingContext jdbcMappingContext(Optional namingStrategy, JdbcCustomConversions customConversions, RelationalManagedTypes jdbcManagedTypes) { - - JdbcMappingContext mappingContext = JdbcMappingContext - .forQuotedIdentifiers(namingStrategy.orElse(DefaultNamingStrategy.INSTANCE)); - mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder()); - mappingContext.setManagedTypes(jdbcManagedTypes); - - return mappingContext; + return JdbcConfiguration.createMappingContext(jdbcManagedTypes, customConversions, namingStrategy.orElse(null)); } /** @@ -143,7 +121,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { */ @Bean public IdGeneratingEntityCallback idGeneratingBeforeSaveCallback(JdbcMappingContext mappingContext, - NamedParameterJdbcOperations operations, Dialect dialect) { + NamedParameterJdbcOperations operations, JdbcDialect dialect) { return new IdGeneratingEntityCallback(mappingContext, dialect, operations); } @@ -157,25 +135,14 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { */ @Bean public JdbcConverter jdbcConverter(JdbcMappingContext mappingContext, NamedParameterJdbcOperations operations, - @Lazy RelationResolver relationResolver, JdbcCustomConversions conversions, Dialect dialect) { - - JdbcArrayColumns arrayColumns = JdbcDialect.getArraySupport(dialect); - DefaultJdbcTypeFactory jdbcTypeFactory = new DefaultJdbcTypeFactory(operations.getJdbcOperations(), arrayColumns); - - MappingJdbcConverter mappingJdbcConverter = new MappingJdbcConverter(mappingContext, relationResolver, conversions, - jdbcTypeFactory); - - if (operations.getJdbcOperations() instanceof JdbcTemplate jdbcTemplate) { - mappingJdbcConverter.setExceptionTranslator(jdbcTemplate.getExceptionTranslator()); - } - - return mappingJdbcConverter; + @Lazy RelationResolver relationResolver, JdbcCustomConversions conversions, JdbcDialect dialect) { + return JdbcConfiguration.createConverter(mappingContext, operations, relationResolver, conversions, dialect); } /** * Register custom {@link Converter}s in a {@link JdbcCustomConversions} object if required. These * {@link JdbcCustomConversions} will be registered with the - * {@link #jdbcConverter(JdbcMappingContext, NamedParameterJdbcOperations, RelationResolver, JdbcCustomConversions, Dialect)}. + * {@link #jdbcConverter(JdbcMappingContext, NamedParameterJdbcOperations, RelationResolver, JdbcCustomConversions, JdbcDialect)}. * Returns an empty {@link JdbcCustomConversions} instance by default. * * @return will never be {@literal null}. @@ -183,31 +150,14 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { @Bean public JdbcCustomConversions jdbcCustomConversions() { - Dialect dialect = applicationContext.getBeanProvider(Dialect.class).getIfAvailable(); - - if (dialect == null) { - LOG.warn("No JdbcDialect bean found; CustomConversions will be configured without dialect-specific types."); - return new JdbcCustomConversions(); - } - - SimpleTypeHolder simpleTypeHolder = new SimpleTypeHolder(dialect.simpleTypes(), JdbcSimpleTypes.HOLDER); - - return new JdbcCustomConversions(CustomConversions.StoreConversions.of(simpleTypeHolder, storeConverters(dialect)), - userConverters()); + JdbcDialect dialect = applicationContext.getBean(JdbcDialect.class); + return JdbcConfiguration.createCustomConversions(dialect, userConverters()); } protected List userConverters() { return Collections.emptyList(); } - private List storeConverters(Dialect dialect) { - - List converters = new ArrayList<>(); - converters.addAll(dialect.getConverters()); - converters.addAll(JdbcCustomConversions.storeConverters()); - return converters; - } - /** * Register a {@link JdbcAggregateTemplate} as a bean for easy use in applications that need a lower level of * abstraction than the normal repository abstraction. @@ -232,8 +182,8 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { */ @Bean public DataAccessStrategy dataAccessStrategyBean(NamedParameterJdbcOperations operations, JdbcConverter jdbcConverter, - JdbcMappingContext context, Dialect dialect) { - return new DataAccessStrategyFactory(jdbcConverter, operations, dialect, this.queryMappingConfiguration).create(); + JdbcMappingContext context, JdbcDialect dialect) { + return JdbcConfiguration.createDataAccessStrategy(operations, jdbcConverter, queryMappingConfiguration, dialect); } /** @@ -245,7 +195,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { * @throws DialectResolver.NoDialectException if the {@link Dialect} cannot be determined. */ @Bean - public Dialect jdbcDialect(NamedParameterJdbcOperations operations) { + public JdbcDialect jdbcDialect(NamedParameterJdbcOperations operations) { return DialectResolver.getDialect(operations.getJdbcOperations()); } @@ -286,16 +236,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { * @return a set of classes identified as entities. * @since 3.0 */ - @SuppressWarnings("unchecked") protected Set> scanForEntities(String basePackage) { - - if (!StringUtils.hasText(basePackage)) { - return Collections.emptySet(); - } - - return TypeScanner.typeScanner(AbstractJdbcConfiguration.class.getClassLoader()) // - .forTypesAnnotatedWith(Table.class) // - .scanPackages(basePackage) // - .collectAsSet(); + return JdbcConfiguration.scanForEntities(basePackage); } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java new file mode 100644 index 000000000..ccd8fab5c --- /dev/null +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java @@ -0,0 +1,168 @@ +/* + * Copyright 2025 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jdbc.repository.config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.jspecify.annotations.Nullable; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.CustomConversions; +import org.springframework.data.jdbc.core.JdbcAggregateOperations; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; +import org.springframework.data.jdbc.core.convert.DataAccessStrategyFactory; +import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory; +import org.springframework.data.jdbc.core.convert.JdbcConverter; +import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; +import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; +import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration; +import org.springframework.data.jdbc.core.convert.RelationResolver; +import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns; +import org.springframework.data.jdbc.core.dialect.JdbcDialect; +import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; +import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.relational.RelationalManagedTypes; +import org.springframework.data.relational.core.dialect.Dialect; +import org.springframework.data.relational.core.mapping.DefaultNamingStrategy; +import org.springframework.data.relational.core.mapping.NamingStrategy; +import org.springframework.data.relational.core.mapping.Table; +import org.springframework.data.util.TypeScanner; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; +import org.springframework.util.StringUtils; + +/** + * Utility class to providing factory methods for JDBC infrastructure components. + *

+ * Mainly for use within the framework or for configuration arrangements that require customization of configuration. + * + * @author Mark Paluch + * @since 4.0 + */ +public final class JdbcConfiguration { + + private JdbcConfiguration() {} + + /** + * Register custom {@link Converter}s in a {@link JdbcCustomConversions} object if required. + * + * @param dialect the JDBC dialect in use. + * @param userConverters list of user converters, must not be {@literal null}. + * @return will never be {@literal null}. + */ + public static JdbcCustomConversions createCustomConversions(JdbcDialect dialect, List userConverters) { + + SimpleTypeHolder simpleTypeHolder = new SimpleTypeHolder(dialect.simpleTypes(), JdbcSimpleTypes.HOLDER); + + return new JdbcCustomConversions(CustomConversions.StoreConversions.of(simpleTypeHolder, storeConverters(dialect)), + userConverters); + } + + private static List storeConverters(Dialect dialect) { + + List converters = new ArrayList<>(); + converters.addAll(dialect.getConverters()); + converters.addAll(JdbcCustomConversions.storeConverters()); + return converters; + } + + /** + * Register a {@link JdbcMappingContext} and apply an optional {@link NamingStrategy}. + * + * @param jdbcManagedTypes JDBC managed types. + * @param customConversions the custom conversions. + * @param namingStrategy optional {@link NamingStrategy}. Use {@link DefaultNamingStrategy#INSTANCE} as fallback. + * @return must not be {@literal null}. + */ + public static JdbcMappingContext createMappingContext(RelationalManagedTypes jdbcManagedTypes, + JdbcCustomConversions customConversions, @Nullable NamingStrategy namingStrategy) { + + JdbcMappingContext mappingContext = JdbcMappingContext + .forQuotedIdentifiers(namingStrategy != null ? namingStrategy : DefaultNamingStrategy.INSTANCE); + mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder()); + mappingContext.setManagedTypes(jdbcManagedTypes); + + return mappingContext; + } + + /** + * Creates a {@link JdbcConverter}. + * + * @param mappingContext must not be {@literal null}. + * @param operations must not be {@literal null}. + * @param relationResolver must not be {@literal null}. + * @param conversions must not be {@literal null}. + * @param dialect the JDBC dialect in use. + * @return must not be {@literal null}. + */ + public static JdbcConverter createConverter(JdbcMappingContext mappingContext, + NamedParameterJdbcOperations operations, RelationResolver relationResolver, JdbcCustomConversions conversions, + JdbcDialect dialect) { + + JdbcArrayColumns arrayColumns = JdbcDialect.getArraySupport(dialect); + DefaultJdbcTypeFactory jdbcTypeFactory = new DefaultJdbcTypeFactory(operations.getJdbcOperations(), arrayColumns); + + MappingJdbcConverter mappingJdbcConverter = new MappingJdbcConverter(mappingContext, relationResolver, conversions, + jdbcTypeFactory); + + if (operations.getJdbcOperations() instanceof JdbcTemplate jdbcTemplate) { + mappingJdbcConverter.setExceptionTranslator(jdbcTemplate.getExceptionTranslator()); + } + + return mappingJdbcConverter; + } + + /** + * Create a {@link DataAccessStrategy} for reuse in the {@link JdbcAggregateOperations} and the {@link JdbcConverter}. + * Override this method to register a bean of type {@link DataAccessStrategy} if your use case requires a more + * specialized {@link DataAccessStrategy}. + * + * @param operations must not be {@literal null}. + * @param jdbcConverter must not be {@literal null}. + * @param mappingConfiguration mapping configuration, can be {@literal null}. + * @param dialect the JDBC dialect in use. + * @return will never be {@literal null}. + */ + public static DataAccessStrategy createDataAccessStrategy(NamedParameterJdbcOperations operations, + JdbcConverter jdbcConverter, @Nullable QueryMappingConfiguration mappingConfiguration, JdbcDialect dialect) { + return new DataAccessStrategyFactory(jdbcConverter, operations, dialect, + mappingConfiguration == null ? QueryMappingConfiguration.EMPTY : mappingConfiguration).create(); + } + + /** + * Scans the given base package for entities, i.e. JDBC-specific types annotated with {@link Table}. + * + * @param basePackage must not be {@literal null}. + * @return a set of classes identified as entities. + */ + @SuppressWarnings("unchecked") + public static Set> scanForEntities(String basePackage) { + + if (!StringUtils.hasText(basePackage)) { + return Collections.emptySet(); + } + + return TypeScanner.typeScanner(JdbcConfiguration.class.getClassLoader()) // + .forTypesAnnotatedWith(Table.class) // + .scanPackages(basePackage) // + .collectAsSet(); + } + +} diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfiguration.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfiguration.java index 6198fab51..66b9f83ce 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfiguration.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfiguration.java @@ -18,15 +18,16 @@ package org.springframework.data.jdbc.repository.config; import java.util.Optional; import org.apache.ibatis.session.SqlSession; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration; +import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy; -import org.springframework.data.relational.core.dialect.Dialect; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; /** @@ -46,7 +47,7 @@ public class MyBatisJdbcConfiguration extends AbstractJdbcConfiguration { @Bean @Override public DataAccessStrategy dataAccessStrategyBean(NamedParameterJdbcOperations operations, JdbcConverter jdbcConverter, - JdbcMappingContext context, Dialect dialect) { + JdbcMappingContext context, JdbcDialect dialect) { return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, jdbcConverter, operations, session, dialect, queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY)); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfigurationIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfigurationIntegrationTests.java index 9c8ee9738..a83005eef 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfigurationIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfigurationIntegrationTests.java @@ -25,6 +25,7 @@ import java.util.Optional; import java.util.function.Consumer; import org.junit.jupiter.api.Test; + import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -36,9 +37,9 @@ import org.springframework.data.jdbc.core.JdbcAggregateTemplate; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; +import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.relational.RelationalManagedTypes; -import org.springframework.data.relational.core.dialect.Dialect; import org.springframework.data.relational.core.dialect.LimitClause; import org.springframework.data.relational.core.dialect.LockClause; import org.springframework.data.relational.core.sql.render.SelectRenderContext; @@ -142,7 +143,7 @@ class AbstractJdbcConfigurationIntegrationTests { @Override @Bean - public Dialect jdbcDialect(NamedParameterJdbcOperations operations) { + public JdbcDialect jdbcDialect(NamedParameterJdbcOperations operations) { return new DummyDialect(); } @@ -165,7 +166,7 @@ class AbstractJdbcConfigurationIntegrationTests { private static class Blubb {} - private static class DummyDialect implements Dialect { + private static class DummyDialect implements JdbcDialect { @Override public LimitClause limit() { return null; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfigurationIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfigurationIntegrationTests.java index b0ad7a4b1..d05023ae1 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfigurationIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfigurationIntegrationTests.java @@ -22,14 +22,14 @@ import java.util.List; import org.apache.ibatis.session.SqlSession; import org.junit.jupiter.api.Test; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jdbc.core.convert.CascadingDataAccessStrategy; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; +import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.core.dialect.JdbcHsqlDbDialect; import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy; -import org.springframework.data.relational.core.dialect.Dialect; -import org.springframework.data.relational.core.dialect.HsqlDbDialect; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.test.util.ReflectionTestUtils; @@ -70,7 +70,7 @@ public class MyBatisJdbcConfigurationIntegrationTests extends AbstractJdbcConfig @Override @Bean - public Dialect jdbcDialect(NamedParameterJdbcOperations operations) { + public JdbcDialect jdbcDialect(NamedParameterJdbcOperations operations) { return JdbcHsqlDbDialect.INSTANCE; } } diff --git a/src/main/antora/modules/ROOT/pages/jdbc/getting-started.adoc b/src/main/antora/modules/ROOT/pages/jdbc/getting-started.adoc index 168712e5a..01bbcdc6a 100644 --- a/src/main/antora/modules/ROOT/pages/jdbc/getting-started.adoc +++ b/src/main/antora/modules/ROOT/pages/jdbc/getting-started.adoc @@ -148,13 +148,13 @@ There are a couple of things one might want to customize in this setup. [[jdbc.dialects]] == Dialects -Spring Data JDBC uses implementations of the interface `Dialect` to encapsulate behavior that is specific to a database or its JDBC driver. -By default, the javadoc:org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration[] attempts to determine the dialect from the database configuration by obtaining a connection and registering the correct `Dialect`. +Spring Data JDBC uses implementations of the interface `JdbcDialect` to encapsulate behavior that is specific to a database or its JDBC driver. +By default, the javadoc:org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration[] attempts to determine the dialect from the database configuration by obtaining a connection and registering the correct `JdbcDialect`. You override `AbstractJdbcConfiguration.jdbcDialect(NamedParameterJdbcOperations)` to customize dialect selection. If you use a database for which no dialect is available, then your application won’t start up. -In that case, you’ll have to ask your vendor to provide a `Dialect` implementation. -Alternatively, you can implement your own `Dialect`. +In that case, you’ll have to ask your vendor to provide a `JdbcDialect` implementation. +Alternatively, you can implement your own `JdbcDialect`. [TIP] ==== @@ -163,8 +163,8 @@ You can let Spring auto-discover your javadoc:org.springframework.data.jdbc.core `DialectResolver` discovers dialect provider implementations from the class path using Spring's `SpringFactoriesLoader`. To do so: -. Implement your own `Dialect`. -. Implement a `JdbcDialectProvider` returning the `Dialect`. +. Implement your own `JdbcDialect`. +. Implement a `JdbcDialectProvider` returning the `JdbcDialect`. . Register the provider by creating a `spring.factories` resource under `META-INF` and perform the registration by adding a line + `org.springframework.data.jdbc.core.dialect.DialectResolver$JdbcDialectProvider`=`. ==== diff --git a/src/main/antora/modules/ROOT/pages/jdbc/mapping.adoc b/src/main/antora/modules/ROOT/pages/jdbc/mapping.adoc index bc363b2ba..61c2d203d 100644 --- a/src/main/antora/modules/ROOT/pages/jdbc/mapping.adoc +++ b/src/main/antora/modules/ROOT/pages/jdbc/mapping.adoc @@ -208,8 +208,8 @@ class MyJdbcConfiguration extends AbstractJdbcConfiguration { ---- NOTE: In previous versions of Spring Data JDBC it was recommended to directly overwrite `AbstractJdbcConfiguration.jdbcCustomConversions()`. -This is no longer necessary or even recommended, since that method assembles conversions intended for all databases, conversions registered by the `Dialect` used and conversions registered by the user. -If you are migrating from an older version of Spring Data JDBC and have `AbstractJdbcConfiguration.jdbcCustomConversions()` overwritten conversions from your `Dialect` will not get registered. +This is no longer necessary or even recommended, since that method assembles conversions intended for all databases, conversions registered by the `JdbcDialect` used and conversions registered by the user. +If you are migrating from an older version of Spring Data JDBC and have `AbstractJdbcConfiguration.jdbcCustomConversions()` overwritten conversions from your `JdbcDialect` will not get registered. [TIP] ==== diff --git a/src/main/antora/modules/ROOT/pages/r2dbc/getting-started.adoc b/src/main/antora/modules/ROOT/pages/r2dbc/getting-started.adoc index afb6df1d1..357d49b9f 100644 --- a/src/main/antora/modules/ROOT/pages/r2dbc/getting-started.adoc +++ b/src/main/antora/modules/ROOT/pages/r2dbc/getting-started.adoc @@ -172,15 +172,15 @@ This approach lets you use the standard `io.r2dbc.spi.ConnectionFactory` instanc [[r2dbc.dialects]] == Dialects -Spring Data R2DBC uses a `Dialect` to encapsulate behavior that is specific to a database or its driver. +Spring Data R2DBC uses a `R2dbcDialect` to encapsulate behavior that is specific to a database or its driver. Spring Data R2DBC reacts to database specifics by inspecting the `ConnectionFactory` and selects the appropriate database dialect accordingly. If you use a database for which no dialect is available, then your application won’t start up. -In that case, you’ll have to ask your vendor to provide a `Dialect` implementation. -Alternatively, you can implement your own `Dialect`. +In that case, you’ll have to ask your vendor to provide a `R2dbcDialect` implementation. +Alternatively, you can implement your own `R2dbcDialect`. [TIP] ==== -Dialects are resolved by javadoc:org.springframework.data.r2dbc./dialect.DialectResolver[] from a `ConnectionFactory`, typically by inspecting `ConnectionFactoryMetadata`. +Dialects are resolved by javadoc:org.springframework.data.r2dbc.dialect.DialectResolver[] from a `ConnectionFactory`, typically by inspecting `ConnectionFactoryMetadata`. + You can let Spring auto-discover your `R2dbcDialect` by registering a class that implements `org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider` through `META-INF/spring.factories`. `DialectResolver` discovers dialect provider implementations from the class path using Spring's `SpringFactoriesLoader`. To do so: diff --git a/src/main/antora/modules/ROOT/pages/r2dbc/mapping.adoc b/src/main/antora/modules/ROOT/pages/r2dbc/mapping.adoc index e25416b9a..4fc7a4482 100644 --- a/src/main/antora/modules/ROOT/pages/r2dbc/mapping.adoc +++ b/src/main/antora/modules/ROOT/pages/r2dbc/mapping.adoc @@ -53,7 +53,7 @@ You can do so by overriding `r2dbcMappingContext(Optional)` of ` Spring Data converts the letter casing of such a name to that form which is also used by the configured database when no quoting is used. Therefore, you can use unquoted names when creating tables, as long as you do not use keywords or special characters in your names. For databases that adhere to the SQL standard, this means that names are converted to upper case. -The quoting character and the way names get capitalized is controlled by the used `Dialect`. +The quoting character and the way names get capitalized is controlled by the used `R2dbcDialect`. See xref:r2dbc/getting-started.adoc#r2dbc.dialects[R2DBC Drivers] for how to configure custom dialects. .@Configuration class to configure R2DBC mapping support