Browse Source

Introduce `JdbcConfiguration` and extract factory methods used from `AbstractJdbcConfiguration`.

Closes: #2165
Original pull request: #2166
pull/2173/head
Mark Paluch 2 months ago
parent
commit
a28a2cd517
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 83
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java
  2. 168
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java
  3. 5
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfiguration.java
  4. 7
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfigurationIntegrationTests.java
  5. 6
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfigurationIntegrationTests.java
  6. 12
      src/main/antora/modules/ROOT/pages/jdbc/getting-started.adoc
  7. 4
      src/main/antora/modules/ROOT/pages/jdbc/mapping.adoc
  8. 8
      src/main/antora/modules/ROOT/pages/r2dbc/getting-started.adoc
  9. 2
      src/main/antora/modules/ROOT/pages/r2dbc/mapping.adoc

83
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java

@ -15,7 +15,6 @@ @@ -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; @@ -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; @@ -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; @@ -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 { @@ -96,7 +80,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
protected Collection<String> 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 { @@ -124,13 +108,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
@Bean
public JdbcMappingContext jdbcMappingContext(Optional<NamingStrategy> 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 { @@ -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 { @@ -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 { @@ -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<Object> storeConverters(Dialect dialect) {
List<Object> 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 { @@ -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 { @@ -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 { @@ -286,16 +236,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
* @return a set of classes identified as entities.
* @since 3.0
*/
@SuppressWarnings("unchecked")
protected Set<Class<?>> 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);
}
}

168
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java

@ -0,0 +1,168 @@ @@ -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.
* <p>
* 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<Object> storeConverters(Dialect dialect) {
List<Object> 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<Class<?>> scanForEntities(String basePackage) {
if (!StringUtils.hasText(basePackage)) {
return Collections.emptySet();
}
return TypeScanner.typeScanner(JdbcConfiguration.class.getClassLoader()) //
.forTypesAnnotatedWith(Table.class) //
.scanPackages(basePackage) //
.collectAsSet();
}
}

5
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; @@ -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 { @@ -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));

7
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfigurationIntegrationTests.java

@ -25,6 +25,7 @@ import java.util.Optional; @@ -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; @@ -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 { @@ -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 { @@ -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;

6
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/MyBatisJdbcConfigurationIntegrationTests.java

@ -22,14 +22,14 @@ import java.util.List; @@ -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 @@ -70,7 +70,7 @@ public class MyBatisJdbcConfigurationIntegrationTests extends AbstractJdbcConfig
@Override
@Bean
public Dialect jdbcDialect(NamedParameterJdbcOperations operations) {
public JdbcDialect jdbcDialect(NamedParameterJdbcOperations operations) {
return JdbcHsqlDbDialect.INSTANCE;
}
}

12
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. @@ -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 @@ -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`=<fully qualified name of your JdbcDialectProvider>`.
====

4
src/main/antora/modules/ROOT/pages/jdbc/mapping.adoc

@ -208,8 +208,8 @@ class MyJdbcConfiguration extends AbstractJdbcConfiguration { @@ -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]
====

8
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 @@ -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:

2
src/main/antora/modules/ROOT/pages/r2dbc/mapping.adoc

@ -53,7 +53,7 @@ You can do so by overriding `r2dbcMappingContext(Optional<NamingStrategy>)` of ` @@ -53,7 +53,7 @@ You can do so by overriding `r2dbcMappingContext(Optional<NamingStrategy>)` 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

Loading…
Cancel
Save