Skip to content

Commit ca77912

Browse files
committed
Refine JavaPoet usage.
See: #2121 Original pull request: #2124
1 parent f6d4b28 commit ca77912

File tree

6 files changed

+88
-86
lines changed

6 files changed

+88
-86
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/JdbcCodeBlocks.java

Lines changed: 56 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.core.annotation.MergedAnnotation;
3535
import org.springframework.data.domain.SliceImpl;
3636
import org.springframework.data.domain.Sort;
37+
import org.springframework.data.javapoet.LordOfTheStrings;
3738
import org.springframework.data.jdbc.repository.query.JdbcQueryMethod;
3839
import org.springframework.data.jdbc.repository.query.Modifying;
3940
import org.springframework.data.jdbc.repository.query.ParameterBinding;
@@ -44,10 +45,10 @@
4445
import org.springframework.data.relational.core.sql.LockMode;
4546
import org.springframework.data.relational.repository.Lock;
4647
import org.springframework.data.repository.aot.generate.AotQueryMethodGenerationContext;
48+
import org.springframework.data.repository.aot.generate.MethodReturn;
4749
import org.springframework.data.repository.query.parser.Part;
4850
import org.springframework.data.support.PageableExecutionUtils;
4951
import org.springframework.data.util.Pair;
50-
import org.springframework.data.util.ReflectionUtils;
5152
import org.springframework.javapoet.CodeBlock;
5253
import org.springframework.javapoet.CodeBlock.Builder;
5354
import org.springframework.javapoet.TypeName;
@@ -58,7 +59,7 @@
5859
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
5960
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
6061
import org.springframework.util.Assert;
61-
import org.springframework.util.ObjectUtils;
62+
import org.springframework.util.ClassUtils;
6263
import org.springframework.util.StringUtils;
6364

6465
/**
@@ -568,25 +569,26 @@ public CodeBlock build() {
568569

569570
Builder builder = CodeBlock.builder();
570571

571-
boolean isProjecting = !ObjectUtils.nullSafeEquals(
572-
TypeName.get(context.getRepositoryInformation().getDomainType()), context.getActualReturnType());
573-
Type actualReturnType = isProjecting ? context.getActualReturnType().getType()
572+
MethodReturn methodReturn = context.getMethodReturn();
573+
boolean isProjecting = methodReturn.isProjecting()
574+
|| StringUtils.hasText(context.getDynamicProjectionParameterName());
575+
Type actualReturnType = isProjecting ? methodReturn.getActualReturnClass()
574576
: context.getRepositoryInformation().getDomainType();
575-
builder.add("\n");
576577

577-
Class<?> returnType = context.getMethod().getReturnType();
578-
TypeName queryResultType = TypeName.get(context.getActualReturnType().toClass());
578+
Class<?> returnType = context.getMethodReturn().toClass();
579+
580+
TypeName queryResultType = methodReturn.getActualClassName();
579581
String result = context.localVariable("result");
580582
String rowMapper = context.localVariable("rowMapper");
581583

582584
if (modifying.isPresent()) {
583-
return update(builder, returnType);
585+
return update(returnType);
584586
} else if (aotQuery.isCount()) {
585-
return count(builder, result, returnType, queryResultType);
587+
return count(result, returnType, queryResultType);
586588
} else if (aotQuery.isExists()) {
587-
return exists(builder, queryResultType);
589+
return exists(queryResultType);
588590
} else if (aotQuery.isDelete()) {
589-
return delete(builder, rowMapper, result, queryResultType, returnType, actualReturnType);
591+
return delete(rowMapper, result, queryResultType, returnType, actualReturnType);
590592
} else {
591593

592594
String resultSetExtractor = null;
@@ -603,7 +605,7 @@ public CodeBlock build() {
603605
if (isProjecting) {
604606
typeToRead = context.getReturnedType().getDomainType();
605607
} else {
606-
typeToRead = context.getActualReturnType().getType();
608+
typeToRead = methodReturn.getActualReturnClass();
607609
}
608610

609611
builder.addStatement("$T $L = getRowMapperFactory().create($T.class)", RowMapper.class, rowMapper,
@@ -667,63 +669,61 @@ public CodeBlock build() {
667669
}
668670

669671
builder.addStatement("return ($T) convertMany($L, %s)".formatted(dynamicProjection ? "$L" : "$T.class"),
670-
context.getReturnTypeName(), result, queryResultTypeRef);
672+
methodReturn.getTypeName(), result, queryResultTypeRef);
671673
} else if (queryMethod.isStreamQuery()) {
672674

673675
builder.addStatement("$1T $2L = getJdbcOperations().queryForStream($3L, $4L, $5L)", Stream.class, result,
674676
queryVariableName, parameterSourceVariableName, rowMapper);
675-
builder.addStatement("return ($T) convertMany($L, $T.class)", context.getReturnTypeName(), result,
677+
builder.addStatement("return ($T) convertMany($L, $T.class)", methodReturn.getTypeName(), result,
676678
queryResultTypeRef);
677679
} else {
678680

679681
builder.addStatement("$T $L = queryForObject($L, $L, $L)", Object.class, result, queryVariableName,
680682
parameterSourceVariableName, rowMapper);
681683

682-
if (Optional.class.isAssignableFrom(context.getReturnType().toClass())) {
684+
if (methodReturn.isOptional()) {
683685
builder.addStatement(
684686
"return ($1T) $1T.ofNullable(convertOne($2L, %s))".formatted(dynamicProjection ? "$3L" : "$3T.class"),
685687
Optional.class, result, queryResultTypeRef);
686688
} else {
687689
builder.addStatement("return ($T) convertOne($L, %s)".formatted(dynamicProjection ? "$L" : "$T.class"),
688-
context.getReturnTypeName(), result, queryResultTypeRef);
690+
methodReturn.getTypeName(), result, queryResultTypeRef);
689691
}
690692
}
691693
}
692694

693695
return builder.build();
694696
}
695697

696-
private CodeBlock update(Builder builder, Class<?> returnType) {
698+
private CodeBlock update(Class<?> returnType) {
697699

698700
String result = context.localVariable("result");
699701

700-
builder.add("$[");
701-
702-
if (!ReflectionUtils.isVoid(returnType)) {
703-
builder.add("int $L = ", result);
704-
}
702+
Builder builder = CodeBlock.builder();
705703

706-
builder.add("getJdbcOperations().update($L, $L)", queryVariableName, parameterSourceVariableName);
707-
builder.add(";\n$]");
704+
LordOfTheStrings.InvocationBuilder invoke = LordOfTheStrings.invoke("getJdbcOperations().update($L, $L)",
705+
queryVariableName, parameterSourceVariableName);
708706

709-
if (returnType == boolean.class || returnType == Boolean.class) {
710-
builder.addStatement("return $L != 0", result);
711-
} else if (returnType == Long.class) {
712-
builder.addStatement("return (long) $L", result);
713-
} else if (ReflectionUtils.isVoid(returnType)) {
714-
if (returnType == Void.class) {
715-
builder.addStatement("return null");
716-
}
707+
if (context.getMethodReturn().isVoid()) {
708+
builder.addStatement(invoke.build());
717709
} else {
718-
builder.addStatement("return $L", result);
710+
builder.addStatement(invoke.assignTo("int $L", result));
719711
}
720712

713+
builder.addStatement(LordOfTheStrings.returning(returnType) //
714+
.whenBoolean("$L != 0", result) //
715+
.whenBoxedLong("(long) $L", result) //
716+
.otherwise("$L", result)//
717+
.build());
718+
721719
return builder.build();
722720
}
723721

724-
private CodeBlock delete(Builder builder, String rowMapper, String result, TypeName queryResultType,
722+
private CodeBlock delete(String rowMapper, String result, TypeName queryResultType,
725723
Class<?> returnType, Type actualReturnType) {
726724

725+
CodeBlock.Builder builder = CodeBlock.builder();
726+
727727
builder.addStatement("$T $L = getRowMapperFactory().create($T.class)", RowMapper.class, rowMapper,
728728
context.getRepositoryInformation().getDomainType());
729729

@@ -732,48 +732,37 @@ private CodeBlock delete(Builder builder, String rowMapper, String result, TypeN
732732

733733
builder.addStatement("$L.forEach(getOperations()::delete)", result);
734734

735-
if (Collection.class.isAssignableFrom(context.getReturnType().toClass())) {
736-
builder.addStatement("return ($T) convertMany($L, $T.class)", context.getReturnTypeName(), result,
737-
queryResultType);
738-
} else if (returnType == context.getRepositoryInformation().getDomainType()) {
739-
builder.addStatement("return ($1T) ($2L.isEmpty() ? null : $2L.iterator().next())", actualReturnType, result);
740-
} else if (returnType == boolean.class || returnType == Boolean.class) {
741-
builder.addStatement("return !$L.isEmpty()", result);
742-
} else if (returnType == Long.class) {
743-
builder.addStatement("return (long) $L.size()", result);
744-
} else if (ReflectionUtils.isVoid(returnType)) {
745-
if (returnType == Void.class) {
746-
builder.addStatement("return null");
747-
}
748-
} else {
749-
builder.addStatement("return $L.size()", result);
750-
}
735+
builder.addStatement(LordOfTheStrings.returning(returnType) //
736+
.when(Collection.class.isAssignableFrom(context.getMethodReturn().toClass()),
737+
"($T) convertMany($L, $T.class)", context.getMethodReturn().getTypeName(), result, queryResultType) //
738+
.when(context.getRepositoryInformation().getDomainType(),
739+
"($1T) ($2L.isEmpty() ? null : $2L.iterator().next())", actualReturnType, result) //
740+
.whenBoolean("!$L.isEmpty()", result) //
741+
.whenBoxedLong("(long) $L.size()", result) //
742+
.otherwise("$L.size()", result) //
743+
.build());
751744

752745
return builder.build();
753746
}
754747

755-
private CodeBlock count(Builder builder, String result, Class<?> returnType, TypeName queryResultType) {
748+
private CodeBlock count(String result, Class<?> returnType, TypeName queryResultType) {
749+
750+
CodeBlock.Builder builder = CodeBlock.builder();
756751

757752
builder.addStatement("$1T $2L = queryForObject($3L, $4L, new $5T<>($1T.class))", Number.class, result,
758753
queryVariableName, parameterSourceVariableName, SingleColumnRowMapper.class);
759754

760-
if (returnType == Long.class) {
761-
builder.addStatement("return $1L != null ? $1L.longValue() : null", result);
762-
} else if (returnType == Integer.class) {
763-
builder.addStatement("return $1L != null ? $1L.intValue() : null", result);
764-
} else if (returnType == Long.TYPE) {
765-
builder.addStatement("return $1L != null ? $1L.longValue() : 0L", result);
766-
} else if (returnType == Integer.TYPE) {
767-
builder.addStatement("return $1L != null ? $1L.intValue() : 0", result);
768-
} else {
769-
builder.addStatement("return ($T) convertOne($L, $T.class)", context.getReturnTypeName(), result,
770-
queryResultType);
771-
}
755+
builder.addStatement(LordOfTheStrings.returning(returnType) //
756+
.number(result) //
757+
.otherwise("($T) convertOne($L, $T.class)", context.getMethodReturn().getTypeName(), result, queryResultType) //
758+
.build());
772759

773760
return builder.build();
774761
}
775762

776-
private CodeBlock exists(Builder builder, TypeName queryResultType) {
763+
private CodeBlock exists(TypeName queryResultType) {
764+
765+
CodeBlock.Builder builder = CodeBlock.builder();
777766

778767
builder.addStatement("return ($T) getJdbcOperations().query($L, $L, $T::next)", queryResultType,
779768
queryVariableName, parameterSourceVariableName, ResultSet.class);
@@ -783,8 +772,8 @@ private CodeBlock exists(Builder builder, TypeName queryResultType) {
783772

784773
public static boolean returnsModifying(Class<?> returnType) {
785774

786-
return returnType == int.class || returnType == long.class || returnType == Integer.class
787-
|| returnType == Long.class;
775+
return ClassUtils.resolvePrimitiveIfNecessary(returnType) == Integer.class
776+
|| ClassUtils.resolvePrimitiveIfNecessary(returnType) == Long.class;
788777
}
789778

790779
}

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/aot/JdbcRepositoryContributor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ protected void customizeConstructor(AotRepositoryConstructorBuilder constructorB
146146
body.add(JdbcCodeBlocks.queryBuilder(context, queryMethod).filter(aotQueries)
147147
.usingQueryVariableName(queryVariable).parameterSource(parameterSourceVariable).lock(lock).build());
148148

149+
body.add("\n");
150+
149151
body.add(JdbcCodeBlocks.executionBuilder(context, queryMethod).modifying(modifying)
150152
.usingQueryVariableName(queryVariable).parameterSource(parameterSourceVariable).queries(aotQueries)
151153
.queryAnnotation(query).build());

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/AotJdbcRepositoryIntegrationTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,21 @@
1515
*/
1616
package org.springframework.data.jdbc.repository;
1717

18+
import java.util.Optional;
19+
1820
import org.springframework.beans.factory.annotation.Autowired;
1921
import org.springframework.context.ApplicationContext;
2022
import org.springframework.context.annotation.Bean;
2123
import org.springframework.context.annotation.ComponentScan;
2224
import org.springframework.context.annotation.Configuration;
2325
import org.springframework.context.annotation.FilterType;
26+
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
27+
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
2428
import org.springframework.data.jdbc.core.dialect.JdbcH2Dialect;
2529
import org.springframework.data.jdbc.repository.aot.AotFragmentTestConfigurationSupport;
2630
import org.springframework.data.jdbc.repository.aot.UserRepository;
2731
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
32+
import org.springframework.data.jdbc.repository.support.BeanFactoryAwareRowMapperFactory;
2833
import org.springframework.data.jdbc.testing.DatabaseType;
2934
import org.springframework.data.jdbc.testing.EnabledOnDatabase;
3035
import org.springframework.data.jdbc.testing.IntegrationTest;
@@ -58,6 +63,13 @@ static AotFragmentTestConfigurationSupport aot() {
5863
false);
5964
}
6065

66+
@Bean
67+
BeanFactoryAwareRowMapperFactory rowMapperFactory(ApplicationContext context,
68+
JdbcAggregateOperations aggregateOperations, Optional<QueryMappingConfiguration> queryMappingConfiguration) {
69+
return new BeanFactoryAwareRowMapperFactory(context, aggregateOperations,
70+
queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY));
71+
}
72+
6173
@Bean
6274
@Override
6375
DummyEntityRepository dummyEntityRepository() {

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/aot/AotFragmentTestConfigurationSupport.java

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.lang.reflect.Proxy;
2020
import java.util.Arrays;
2121
import java.util.List;
22-
import java.util.Optional;
2322

2423
import org.mockito.Mockito;
2524

@@ -34,9 +33,6 @@
3433
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
3534
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3635
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
37-
import org.springframework.context.ApplicationContext;
38-
import org.springframework.context.ApplicationContextAware;
39-
import org.springframework.context.annotation.Bean;
4036
import org.springframework.core.env.Environment;
4137
import org.springframework.core.env.StandardEnvironment;
4238
import org.springframework.core.io.DefaultResourceLoader;
@@ -45,12 +41,10 @@
4541
import org.springframework.data.expression.ValueExpressionParser;
4642
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
4743
import org.springframework.data.jdbc.core.convert.MappingJdbcConverter;
48-
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
4944
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
5045
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
5146
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
5247
import org.springframework.data.jdbc.repository.query.RowMapperFactory;
53-
import org.springframework.data.jdbc.repository.support.BeanFactoryAwareRowMapperFactory;
5448
import org.springframework.data.projection.ProjectionFactory;
5549
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
5650
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
@@ -71,13 +65,12 @@
7165
*
7266
* @author Mark Paluch
7367
*/
74-
public class AotFragmentTestConfigurationSupport implements BeanFactoryPostProcessor, ApplicationContextAware {
68+
public class AotFragmentTestConfigurationSupport implements BeanFactoryPostProcessor {
7569

7670
private final Class<?> repositoryInterface;
7771
private final JdbcDialect dialect;
7872
private final boolean registerFragmentFacade;
7973
private final TestJdbcAotRepositoryContext<?> repositoryContext;
80-
private ApplicationContext applicationContext;
8174

8275
public AotFragmentTestConfigurationSupport(Class<?> repositoryInterface, JdbcDialect dialect, Class<?> configClass) {
8376
this(repositoryInterface, dialect, configClass, true);
@@ -98,13 +91,6 @@ EnableJdbcRepositories.class, new DefaultResourceLoader(), new StandardEnvironme
9891
this.registerFragmentFacade = registerFragmentFacade;
9992
}
10093

101-
@Bean
102-
BeanFactoryAwareRowMapperFactory rowMapperFactory(ApplicationContext context,
103-
JdbcAggregateOperations aggregateOperations, Optional<QueryMappingConfiguration> queryMappingConfiguration) {
104-
return new BeanFactoryAwareRowMapperFactory(context, aggregateOperations,
105-
queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY));
106-
}
107-
10894
@Override
10995
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
11096

@@ -191,8 +177,4 @@ public ProjectionFactory getProjectionFactory() {
191177
return creationContext;
192178
}
193179

194-
@Override
195-
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
196-
this.applicationContext = applicationContext;
197-
}
198180
}

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/aot/JdbcRepositoryContributorIntegrationTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import java.util.List;
21+
import java.util.Optional;
2122

2223
import org.junit.jupiter.api.BeforeEach;
2324
import org.junit.jupiter.api.Test;
2425

2526
import org.springframework.beans.factory.annotation.Autowired;
27+
import org.springframework.context.ApplicationContext;
2628
import org.springframework.context.annotation.Bean;
2729
import org.springframework.context.annotation.ComponentScan;
2830
import org.springframework.context.annotation.Configuration;
@@ -34,8 +36,10 @@
3436
import org.springframework.data.domain.Slice;
3537
import org.springframework.data.domain.Sort;
3638
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
39+
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
3740
import org.springframework.data.jdbc.core.dialect.JdbcH2Dialect;
3841
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
42+
import org.springframework.data.jdbc.repository.support.BeanFactoryAwareRowMapperFactory;
3943
import org.springframework.data.jdbc.testing.DatabaseType;
4044
import org.springframework.data.jdbc.testing.EnabledOnDatabase;
4145
import org.springframework.data.jdbc.testing.IntegrationTest;
@@ -71,6 +75,13 @@ TestClass testClass() {
7175
return TestClass.of(JdbcRepositoryContributorIntegrationTests.class);
7276
}
7377

78+
@Bean
79+
BeanFactoryAwareRowMapperFactory rowMapperFactory(ApplicationContext context,
80+
JdbcAggregateOperations aggregateOperations, Optional<QueryMappingConfiguration> queryMappingConfiguration) {
81+
return new BeanFactoryAwareRowMapperFactory(context, aggregateOperations,
82+
queryMappingConfiguration.orElse(QueryMappingConfiguration.EMPTY));
83+
}
84+
7485
@Bean
7586
MyRowMapper myRowMapper() {
7687
return new MyRowMapper();

0 commit comments

Comments
 (0)