From 04bed6ac78fffe0aed8b93421cb330ff9d12fa9f Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 15 Sep 2025 16:42:33 +0200 Subject: [PATCH] Reduce dependencies during AOT contribution. Closes #2136 --- .../aot/JdbcRepositoryContributor.java | 9 ++--- .../jdbc/repository/aot/QueriesFactory.java | 38 +++++-------------- .../config/AbstractJdbcConfiguration.java | 2 +- .../config/JdbcRepositoryConfigExtension.java | 21 +++++++++- .../repository/query/JdbcQueryCreator.java | 4 +- .../repository/query/StatementFactory.java | 2 - .../AotFragmentTestConfigurationSupport.java | 3 +- 7 files changed, 35 insertions(+), 44 deletions(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/JdbcRepositoryContributor.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/JdbcRepositoryContributor.java index dedf1b2f1..296697dee 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/JdbcRepositoryContributor.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/JdbcRepositoryContributor.java @@ -23,7 +23,6 @@ import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.data.jdbc.core.JdbcAggregateOperations; -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.repository.query.JdbcQueryMethod; @@ -62,15 +61,15 @@ public class JdbcRepositoryContributor extends RepositoryContributor { private final @Nullable String jdbcAggregateOperationsRef; public JdbcRepositoryContributor(AotRepositoryContext repositoryContext, JdbcDialect dialect, - JdbcConverter converter) { + RelationalMappingContext mappingContext) { super(repositoryContext); - this.mappingContext = converter.getMappingContext(); + this.mappingContext = mappingContext; RepositoryConfigurationSource configurationSource = repositoryContext.getConfigurationSource(); - this.queriesFactory = new QueriesFactory(configurationSource, converter, dialect, + this.queriesFactory = new QueriesFactory(configurationSource, dialect, mappingContext, repositoryContext.getRequiredClassLoader(), ValueExpressionDelegate.create()); jdbcAggregateOperationsRef = configurationSource.getAttribute("jdbcAggregateOperationsRef").orElse(null); @@ -116,9 +115,7 @@ public class JdbcRepositoryContributor extends RepositoryContributor { queriesFactory.getNamedQueries(), mappingContext); ReturnedType returnedType = queryMethod.getResultProcessor().getReturnedType(); - MergedAnnotation query = MergedAnnotations.from(method).get(Query.class); - AotQueries aotQueries = queriesFactory.createQueries(getRepositoryInformation(), returnedType, query, queryMethod); if (queryMethod.isModifyingQuery()) { diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/QueriesFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/QueriesFactory.java index a4f8f488e..877d6f8bf 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/QueriesFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/QueriesFactory.java @@ -16,7 +16,6 @@ package org.springframework.data.jdbc.repository.aot; import java.io.IOException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -28,6 +27,9 @@ import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.data.domain.Sort; import org.springframework.data.jdbc.core.convert.JdbcConverter; +import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; +import org.springframework.data.jdbc.core.convert.JdbcTypeFactory; +import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.repository.config.JdbcRepositoryConfigExtension; import org.springframework.data.jdbc.repository.query.JdbcCountQueryCreator; @@ -37,11 +39,11 @@ import org.springframework.data.jdbc.repository.query.JdbcQueryMethod; import org.springframework.data.jdbc.repository.query.ParameterBinding; import org.springframework.data.jdbc.repository.query.ParametrizedQuery; import org.springframework.data.jdbc.repository.query.Query; +import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.relational.repository.query.ParameterMetadataProvider; import org.springframework.data.relational.repository.query.RelationalParameterAccessor; import org.springframework.data.relational.repository.query.RelationalParameters; import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor; -import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext; import org.springframework.data.repository.config.PropertiesBasedNamedQueriesFactoryBean; import org.springframework.data.repository.config.RepositoryConfigurationSource; import org.springframework.data.repository.core.NamedQueries; @@ -66,11 +68,13 @@ class QueriesFactory { private final NamedQueries namedQueries; private final ValueExpressionDelegate delegate; - public QueriesFactory(RepositoryConfigurationSource configurationSource, JdbcConverter converter, JdbcDialect dialect, - ClassLoader classLoader, ValueExpressionDelegate delegate) { + public QueriesFactory(RepositoryConfigurationSource configurationSource, JdbcDialect dialect, + RelationalMappingContext mappingContext, ClassLoader classLoader, ValueExpressionDelegate delegate) { + + this.converter = new MappingJdbcConverter(mappingContext, (identifier, path) -> List.of(), + JdbcCustomConversions.of(dialect, List.of()), JdbcTypeFactory.unsupported()); this.namedQueries = getNamedQueries(configurationSource, classLoader); - this.converter = converter; this.dialect = dialect; this.delegate = delegate; } @@ -198,30 +202,6 @@ class QueriesFactory { return PlaceholderAccessor.capture(queryMethod, parameterValues, parameters, bindable); } - public static @Nullable Class getQueryReturnType(AotQuery query, ReturnedType returnedType, - AotQueryMethodGenerationContext context) { - - Method method = context.getMethod(); - RepositoryInformation repositoryInformation = context.getRepositoryInformation(); - - Class methodReturnType = repositoryInformation.getReturnedDomainClass(method); - boolean queryForEntity = repositoryInformation.getDomainType().isAssignableFrom(methodReturnType); - - Class result = queryForEntity ? returnedType.getDomainType() : null; - - if (returnedType.isProjecting()) { - - if (returnedType.getReturnedType().isInterface()) { - - return result; - } - - return returnedType.getReturnedType(); - } - - return result; - } - private ValueExpressionQueryRewriter.ParsedQuery parseQuery(String queryString) { ValueExpressionQueryRewriter rewriter = ValueExpressionQueryRewriter.of(delegate, 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 39047b2e8..bdc1f3c1f 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 @@ -186,7 +186,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { Dialect dialect = applicationContext.getBeanProvider(Dialect.class).getIfAvailable(); if (dialect == null) { - LOG.warn("No dialect found; CustomConversions will be configured without dialect-specific types."); + LOG.warn("No JdbcDialect bean found; CustomConversions will be configured without dialect-specific types."); return new JdbcCustomConversions(); } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcRepositoryConfigExtension.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcRepositoryConfigExtension.java index 3525f68f0..2af7d1368 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcRepositoryConfigExtension.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcRepositoryConfigExtension.java @@ -31,11 +31,15 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionValidationException; import org.springframework.data.jdbc.core.JdbcAggregateOperations; 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.jdbc.repository.aot.JdbcRepositoryContributor; import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactoryBean; 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.RelationalMappingContext; import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.repository.config.AotRepositoryContext; import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport; @@ -157,9 +161,22 @@ public class JdbcRepositoryConfigExtension extends RepositoryConfigurationExtens ConfigurableListableBeanFactory beanFactory = repositoryContext.getBeanFactory(); JdbcDialect dialect = beanFactory.getBean(JdbcDialect.class); - JdbcConverter converter = beanFactory.getBean(JdbcConverter.class); + RelationalMappingContext mappingContext = beanFactory.getBeanProvider(RelationalMappingContext.class) + .getIfAvailable(() -> { - return new JdbcRepositoryContributor(repositoryContext, dialect, converter); + JdbcCustomConversions customConversions = beanFactory.getBeanProvider(JdbcCustomConversions.class) + .getIfAvailable(() -> JdbcCustomConversions.of(dialect, Collections.emptyList())); + + NamingStrategy namingStrategy = beanFactory.getBeanProvider(NamingStrategy.class) + .getIfAvailable(DefaultNamingStrategy::new); + + JdbcMappingContext context = new JdbcMappingContext(namingStrategy); + context.setSimpleTypeHolder(customConversions.getSimpleTypeHolder()); + + return context; + }); + + return new JdbcRepositoryContributor(repositoryContext, dialect, mappingContext); } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java index 5ad507bfe..236e03347 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java @@ -18,7 +18,7 @@ package org.springframework.data.jdbc.repository.query; import java.util.Optional; import org.jspecify.annotations.Nullable; -import org.springframework.data.domain.Pageable; + import org.springframework.data.domain.Sort; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.SqlGeneratorSource; @@ -99,7 +99,7 @@ public class JdbcQueryCreator extends RelationalQueryCreator RelationalParameterAccessor accessor, ReturnedType returnedType) { this(converter.getMappingContext(), tree, converter, dialect, queryMethod.getEntityInformation(), accessor, queryMethod.isSliceQuery(), returnedType, queryMethod.lookupLockAnnotation(), - new SqlGeneratorSource(converter.getMappingContext(), converter, dialect)); + new SqlGeneratorSource(converter, dialect)); } /** diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java index 3aea713e2..b4efa8306 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java @@ -56,13 +56,11 @@ import org.springframework.lang.Contract; public class StatementFactory { private final JdbcConverter converter; - private final Dialect dialect; private final RenderContextFactory renderContextFactory; private final QueryMapper queryMapper; private final SqlGeneratorSource sqlGeneratorSource; public StatementFactory(JdbcConverter converter, Dialect dialect) { - this.dialect = dialect; this.renderContextFactory = new RenderContextFactory(dialect); this.converter = converter; this.queryMapper = new QueryMapper(converter); diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/aot/AotFragmentTestConfigurationSupport.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/aot/AotFragmentTestConfigurationSupport.java index 6e3f69d31..d6e632d90 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/aot/AotFragmentTestConfigurationSupport.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/aot/AotFragmentTestConfigurationSupport.java @@ -40,7 +40,6 @@ import org.springframework.core.test.tools.TestCompiler; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.expression.ValueExpressionParser; import org.springframework.data.jdbc.core.JdbcAggregateOperations; -import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; import org.springframework.data.jdbc.core.dialect.JdbcDialect; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories; @@ -99,7 +98,7 @@ public class AotFragmentTestConfigurationSupport implements BeanFactoryPostProce repositoryContext.setBeanFactory(beanFactory); JdbcRepositoryContributor jdbcRepositoryContributor = new JdbcRepositoryContributor(repositoryContext, dialect, - new MappingJdbcConverter(new JdbcMappingContext(), (identifier, path) -> null)); + new JdbcMappingContext()); jdbcRepositoryContributor.contribute(generationContext); AbstractBeanDefinition aotGeneratedRepository = BeanDefinitionBuilder