> 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 0000000000..90f84186a0
--- /dev/null
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java
@@ -0,0 +1,169 @@
+/*
+ * 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 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;
+ }
+
+ /**
+ * 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