@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025 the original author or authors.
|
||||
* 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.
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.validation.constraints.Null;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.data.jpa.repository.query.DeclaredQuery;
|
||||
import org.springframework.data.jpa.repository.query.QueryEnhancer;
|
||||
import org.springframework.data.jpa.repository.query.QueryEnhancerSelector;
|
||||
@@ -35,7 +36,8 @@ record AotQueries(AotQuery result, AotQuery count) {
|
||||
/**
|
||||
* Derive a count query from the given query.
|
||||
*/
|
||||
public static AotQueries from(StringAotQuery query, @Null String countProjection, QueryEnhancerSelector selector) {
|
||||
public static AotQueries from(StringAotQuery query, @Nullable String countProjection,
|
||||
QueryEnhancerSelector selector) {
|
||||
return from(query, StringAotQuery::getQuery, countProjection, selector);
|
||||
}
|
||||
|
||||
@@ -43,7 +45,7 @@ record AotQueries(AotQuery result, AotQuery count) {
|
||||
* Derive a count query from the given query.
|
||||
*/
|
||||
public static <T extends AotQuery> AotQueries from(T query, Function<T, DeclaredQuery> queryMapper,
|
||||
@Null String countProjection, QueryEnhancerSelector selector) {
|
||||
@Nullable String countProjection, QueryEnhancerSelector selector) {
|
||||
|
||||
DeclaredQuery underlyingQuery = queryMapper.apply(query);
|
||||
QueryEnhancer queryEnhancer = selector.select(underlyingQuery).create(underlyingQuery);
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.repository.core.support.RepositoryFactoryBeanSup
|
||||
import org.springframework.data.repository.query.ParametersSource;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.repository.query.ValueExpressionDelegate;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.util.ConcurrentLruCache;
|
||||
|
||||
/**
|
||||
@@ -48,11 +49,11 @@ public class AotRepositoryFragmentSupport {
|
||||
|
||||
private final ProjectionFactory projectionFactory;
|
||||
|
||||
private final ConcurrentLruCache<DeclaredQuery, QueryEnhancer> enhancers;
|
||||
private final Lazy<ConcurrentLruCache<DeclaredQuery, QueryEnhancer>> enhancers;
|
||||
|
||||
private final ConcurrentLruCache<String, ValueExpression> expressions;
|
||||
private final Lazy<ConcurrentLruCache<String, ValueExpression>> expressions;
|
||||
|
||||
private final ConcurrentLruCache<Method, ValueEvaluationContextProvider> contextProviders;
|
||||
private final Lazy<ConcurrentLruCache<Method, ValueEvaluationContextProvider>> contextProviders;
|
||||
|
||||
protected AotRepositoryFragmentSupport(QueryEnhancerSelector selector,
|
||||
RepositoryFactoryBeanSupport.FragmentCreationContext context) {
|
||||
@@ -66,10 +67,10 @@ public class AotRepositoryFragmentSupport {
|
||||
this.repositoryMetadata = repositoryMetadata;
|
||||
this.valueExpressions = valueExpressions;
|
||||
this.projectionFactory = projectionFactory;
|
||||
this.enhancers = new ConcurrentLruCache<>(32, query -> selector.select(query).create(query));
|
||||
this.expressions = new ConcurrentLruCache<>(32, valueExpressions::parse);
|
||||
this.contextProviders = new ConcurrentLruCache<>(32, it -> valueExpressions
|
||||
.createValueContextProvider(new JpaParameters(ParametersSource.of(repositoryMetadata, it))));
|
||||
this.enhancers = Lazy.of(() -> new ConcurrentLruCache<>(32, query -> selector.select(query).create(query)));
|
||||
this.expressions = Lazy.of(() -> new ConcurrentLruCache<>(32, valueExpressions::parse));
|
||||
this.contextProviders = Lazy.of(() -> new ConcurrentLruCache<>(32, it -> valueExpressions
|
||||
.createValueContextProvider(new JpaParameters(ParametersSource.of(repositoryMetadata, it)))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +83,7 @@ public class AotRepositoryFragmentSupport {
|
||||
*/
|
||||
protected String rewriteQuery(DeclaredQuery query, Sort sort, Class<?> returnedType) {
|
||||
|
||||
QueryEnhancer queryStringEnhancer = this.enhancers.get(query);
|
||||
QueryEnhancer queryStringEnhancer = this.enhancers.get().get(query);
|
||||
return queryStringEnhancer.rewrite(new DefaultQueryRewriteInformation(sort,
|
||||
ReturnedType.of(returnedType, repositoryMetadata.getDomainType(), projectionFactory)));
|
||||
}
|
||||
@@ -97,8 +98,8 @@ public class AotRepositoryFragmentSupport {
|
||||
*/
|
||||
protected @Nullable Object evaluateExpression(Method method, String expressionString, Object... args) {
|
||||
|
||||
ValueExpression expression = this.expressions.get(expressionString);
|
||||
ValueEvaluationContextProvider contextProvider = this.contextProviders.get(method);
|
||||
ValueExpression expression = this.expressions.get().get(expressionString);
|
||||
ValueEvaluationContextProvider contextProvider = this.contextProviders.get().get(method);
|
||||
|
||||
return expression.evaluate(contextProvider.getEvaluationContext(args, expression.getExpressionDependencies()));
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.Query;
|
||||
@@ -55,7 +55,6 @@ import org.springframework.util.StringUtils;
|
||||
class JpaCodeBlocks {
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @return new {@link QueryBlockBuilder}.
|
||||
*/
|
||||
public static QueryBlockBuilder queryBuilder(AotQueryMethodGenerationContext context, JpaQueryMethod queryMethod) {
|
||||
@@ -63,7 +62,6 @@ class JpaCodeBlocks {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @return new {@link QueryExecutionBlockBuilder}.
|
||||
*/
|
||||
static QueryExecutionBlockBuilder executionBuilder(AotQueryMethodGenerationContext context,
|
||||
@@ -79,9 +77,8 @@ class JpaCodeBlocks {
|
||||
private final AotQueryMethodGenerationContext context;
|
||||
private final JpaQueryMethod queryMethod;
|
||||
private String queryVariableName = "query";
|
||||
private AotQueries queries;
|
||||
private @Nullable AotQueries queries;
|
||||
private MergedAnnotation<QueryHints> queryHints = MergedAnnotation.missing();
|
||||
private MergedAnnotation<org.springframework.data.jpa.repository.Query> query = MergedAnnotation.missing();
|
||||
private @Nullable String sqlResultSetMapping;
|
||||
private @Nullable Class<?> queryReturnType;
|
||||
|
||||
@@ -101,18 +98,6 @@ class JpaCodeBlocks {
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBlockBuilder queryHints(MergedAnnotation<QueryHints> queryHints) {
|
||||
|
||||
this.queryHints = queryHints;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBlockBuilder query(MergedAnnotation<org.springframework.data.jpa.repository.Query> query) {
|
||||
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBlockBuilder nativeQuery(MergedAnnotation<NativeQuery> nativeQuery) {
|
||||
|
||||
if (nativeQuery.isPresent()) {
|
||||
@@ -121,6 +106,12 @@ class JpaCodeBlocks {
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBlockBuilder queryHints(MergedAnnotation<QueryHints> queryHints) {
|
||||
|
||||
this.queryHints = queryHints;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBlockBuilder queryReturnType(@Nullable Class<?> queryReturnType) {
|
||||
this.queryReturnType = queryReturnType;
|
||||
return this;
|
||||
@@ -142,7 +133,7 @@ class JpaCodeBlocks {
|
||||
|
||||
String queryStringNameVariableName = null;
|
||||
|
||||
if (queries.result() instanceof StringAotQuery sq) {
|
||||
if (queries != null && queries.result() instanceof StringAotQuery sq) {
|
||||
|
||||
queryStringNameVariableName = "%sString".formatted(queryVariableName);
|
||||
builder.addStatement("$T $L = $S", String.class, queryStringNameVariableName, sq.getQueryString());
|
||||
@@ -157,9 +148,6 @@ class JpaCodeBlocks {
|
||||
builder.addStatement("$T $L = $S", String.class, countQueryStringNameVariableName, sq.getQueryString());
|
||||
}
|
||||
|
||||
// sorting
|
||||
// TODO: refactor into sort builder
|
||||
|
||||
String sortParameterName = context.getSortParameterName();
|
||||
if (sortParameterName == null && context.getPageableParameterName() != null) {
|
||||
sortParameterName = "%s.getSort()".formatted(context.getPageableParameterName());
|
||||
@@ -202,7 +190,7 @@ class JpaCodeBlocks {
|
||||
builder.beginControlFlow("if ($L.isSorted())", sort);
|
||||
|
||||
builder.addStatement("$T declaredQuery = $T.$L($L)", DeclaredQuery.class, DeclaredQuery.class,
|
||||
queries.isNative() ? "nativeQuery" : "jpqlQuery",
|
||||
queries != null && queries.isNative() ? "nativeQuery" : "jpqlQuery",
|
||||
queryString);
|
||||
|
||||
builder.addStatement("$L = rewriteQuery(declaredQuery, $L, $T.class)", queryString, sort, actualReturnType);
|
||||
@@ -227,7 +215,7 @@ class JpaCodeBlocks {
|
||||
builder.beginControlFlow("if ($L.isLimited())", limit);
|
||||
builder.addStatement("$L.setMaxResults($L.max())", queryVariableName, limit);
|
||||
builder.endControlFlow();
|
||||
} else if (queries.result().isLimited()) {
|
||||
} else if (queries != null && queries.result().isLimited()) {
|
||||
builder.addStatement("$L.setMaxResults($L)", queryVariableName, queries.result().getLimit().max());
|
||||
}
|
||||
|
||||
@@ -358,7 +346,7 @@ class JpaCodeBlocks {
|
||||
|
||||
Builder builder = CodeBlock.builder();
|
||||
ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
|
||||
String[] parameterNames = discoverer.getParameterNames(context.getMethod());
|
||||
var parameterNames = discoverer.getParameterNames(context.getMethod());
|
||||
|
||||
String expressionString = expr.expression().getExpressionString();
|
||||
// re-wrap expression
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024-2025 the original author or authors.
|
||||
* 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.
|
||||
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.TypedQueryReference;
|
||||
import jakarta.persistence.metamodel.Metamodel;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
@@ -57,6 +58,7 @@ import org.springframework.data.repository.core.support.RepositoryFactoryBeanSup
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.javapoet.TypeName;
|
||||
import org.springframework.javapoet.TypeSpec;
|
||||
@@ -76,13 +78,23 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class JpaRepositoryContributor extends RepositoryContributor {
|
||||
|
||||
private final AotMetamodel metaModel;
|
||||
private final EntityManagerFactory emf;
|
||||
private final Metamodel metaModel;
|
||||
private final PersistenceProvider persistenceProvider;
|
||||
|
||||
public JpaRepositoryContributor(AotRepositoryContext repositoryContext) {
|
||||
super(repositoryContext);
|
||||
this.metaModel = new AotMetamodel(repositoryContext.getResolvedTypes());
|
||||
this.persistenceProvider = PersistenceProvider.fromEntityManagerFactory(metaModel.getEntityManagerFactory());
|
||||
AotMetamodel amm = new AotMetamodel(repositoryContext.getResolvedTypes());
|
||||
this.metaModel = amm;
|
||||
this.emf = amm.getEntityManagerFactory();
|
||||
this.persistenceProvider = PersistenceProvider.fromEntityManagerFactory(amm.getEntityManagerFactory());
|
||||
}
|
||||
|
||||
public JpaRepositoryContributor(AotRepositoryContext repositoryContext, EntityManagerFactory entityManagerFactory) {
|
||||
super(repositoryContext);
|
||||
this.emf = entityManagerFactory;
|
||||
this.metaModel = entityManagerFactory.getMetamodel();
|
||||
this.persistenceProvider = PersistenceProvider.fromEntityManagerFactory(entityManagerFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,6 +130,17 @@ public class JpaRepositoryContributor extends RepositoryContributor {
|
||||
return null;
|
||||
}
|
||||
|
||||
ReturnedType returnedType = queryMethod.getResultProcessor().getReturnedType();
|
||||
|
||||
// no interface/dynamic projections for now.
|
||||
if (returnedType.isProjecting() && returnedType.getReturnedType().isInterface()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (queryMethod.getParameters().hasDynamicProjection()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// no KeysetScrolling for now.
|
||||
if (queryMethod.getParameters().hasScrollPositionParameter()) {
|
||||
return null;
|
||||
@@ -125,9 +148,13 @@ public class JpaRepositoryContributor extends RepositoryContributor {
|
||||
|
||||
if (queryMethod.isModifyingQuery()) {
|
||||
|
||||
Class<?> returnType = repositoryInformation.getReturnType(method).getType();
|
||||
if (!ClassUtils.isVoidType(returnType)
|
||||
&& !JpaCodeBlocks.QueryExecutionBlockBuilder.returnsModifying(returnType)) {
|
||||
TypeInformation<?> returnType = repositoryInformation.getReturnType(method);
|
||||
|
||||
boolean returnsCount = JpaCodeBlocks.QueryExecutionBlockBuilder.returnsModifying(returnType.getType());
|
||||
|
||||
boolean isVoid = ClassUtils.isVoidType(returnType.getType());
|
||||
|
||||
if (!returnsCount && !isVoid) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -140,15 +167,14 @@ public class JpaRepositoryContributor extends RepositoryContributor {
|
||||
MergedAnnotation<NativeQuery> nativeQuery = context.getAnnotation(NativeQuery.class);
|
||||
MergedAnnotation<QueryHints> queryHints = context.getAnnotation(QueryHints.class);
|
||||
MergedAnnotation<Modifying> modifying = context.getAnnotation(Modifying.class);
|
||||
ReturnedType returnedType = context.getReturnedType();
|
||||
|
||||
body.add(context.codeBlocks().logDebug("invoking [%s]".formatted(context.getMethod().getName())));
|
||||
|
||||
AotQueries aotQueries = getQueries(context, query, selector, queryMethod, returnedType);
|
||||
|
||||
body.add(JpaCodeBlocks.queryBuilder(context, queryMethod).filter(aotQueries)
|
||||
.queryReturnType(getQueryReturnType(aotQueries.result(), returnedType, context)).query(query)
|
||||
.nativeQuery(nativeQuery).queryHints(queryHints).build());
|
||||
.queryReturnType(getQueryReturnType(aotQueries.result(), returnedType, context)).nativeQuery(nativeQuery)
|
||||
.queryHints(queryHints).build());
|
||||
|
||||
body.add(
|
||||
JpaCodeBlocks.executionBuilder(context, queryMethod).modifying(modifying).query(aotQueries.result()).build());
|
||||
@@ -178,8 +204,7 @@ public class JpaRepositoryContributor extends RepositoryContributor {
|
||||
|
||||
UnaryOperator<String> operator = s -> s.replaceAll("#\\{#entityName}", domainType.getName());
|
||||
boolean isNative = query.getBoolean("nativeQuery");
|
||||
Function<String, StringAotQuery> queryFunction = isNative ? StringAotQuery::nativeQuery
|
||||
: StringAotQuery::jpqlQuery;
|
||||
Function<String, StringAotQuery> queryFunction = isNative ? StringAotQuery::nativeQuery : StringAotQuery::jpqlQuery;
|
||||
queryFunction = operator.andThen(queryFunction);
|
||||
|
||||
String queryString = query.getString("value");
|
||||
@@ -252,8 +277,6 @@ public class JpaRepositoryContributor extends RepositoryContributor {
|
||||
returnedType.getReturnedType(), returnedType.getTypeToRead(), void.class, null, Long.class, Integer.class,
|
||||
Long.TYPE, Integer.TYPE, Number.class);
|
||||
|
||||
EntityManagerFactory emf = metaModel.getEntityManagerFactory();
|
||||
|
||||
for (Class<?> candidate : candidates) {
|
||||
|
||||
Map<String, ? extends TypedQueryReference<?>> namedQueries = emf.getNamedQueries(candidate);
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Ahead-of-Time (AOT) generation for Spring Data JPA repositories.
|
||||
*/
|
||||
@org.jspecify.annotations.NullMarked
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
@@ -52,7 +52,7 @@ import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.aot.AotContext;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.aot.generated.JpaRepositoryContributor;
|
||||
import org.springframework.data.jpa.repository.aot.JpaRepositoryContributor;
|
||||
import org.springframework.data.jpa.repository.support.DefaultJpaContext;
|
||||
import org.springframework.data.jpa.repository.support.EntityManagerBeanDefinitionRegistrarPostProcessor;
|
||||
import org.springframework.data.jpa.repository.support.JpaEvaluationContextExtension;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* 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.
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
@@ -399,9 +399,10 @@ class JpaRepositoryContributorIntegrationTests {
|
||||
assertThat(page.getContent()).extracting(UserDtoProjection::getEmailAddress).containsExactly("han@smuggler.net",
|
||||
"kylo@new-empire.com");
|
||||
|
||||
// TODO
|
||||
Page<UserDtoProjection> noResults = fragment.findUserProjectionByLastnameStartingWith("a",
|
||||
PageRequest.of(0, 2, Sort.by("emailAddress")));
|
||||
|
||||
assertThat(noResults).isEmpty();
|
||||
}
|
||||
|
||||
// modifying
|
||||
@@ -419,6 +420,13 @@ class JpaRepositoryContributorIntegrationTests {
|
||||
assertThat(yodaShouldBeGone).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldOmitAnnotatedDeleteReturningDomainType() {
|
||||
|
||||
assertThatException().isThrownBy(() -> fragment.deleteAnnotatedQueryByEmailAddress("foo"))
|
||||
.withRootCauseInstanceOf(NoSuchMethodException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyModifying() {
|
||||
|
||||
@@ -456,11 +464,11 @@ class JpaRepositoryContributorIntegrationTests {
|
||||
|
||||
void todo() {
|
||||
|
||||
// entity graphs
|
||||
// interface projections
|
||||
// dynamic projections
|
||||
// class type parameter
|
||||
|
||||
// entity graphs
|
||||
// synthetic parameters (keyset scrolling! yuck!)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* 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.
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
* 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.
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.aot.generated;
|
||||
package org.springframework.data.jpa.repository.aot;
|
||||
|
||||
import jakarta.persistence.QueryHint;
|
||||
|
||||
@@ -131,8 +131,7 @@ interface UserRepository extends CrudRepository<User, Integer> {
|
||||
|
||||
User deleteByEmailAddress(String username);
|
||||
|
||||
Long deleteReturningDeleteCountByEmailAddress(String username);
|
||||
|
||||
// cannot generate delete and return a domain object
|
||||
@Modifying
|
||||
@Query("delete from User u where u.emailAddress = ?1")
|
||||
User deleteAnnotatedQueryByEmailAddress(String username);
|
||||
@@ -24,6 +24,7 @@ import jakarta.persistence.Query;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
@@ -169,7 +170,7 @@ class JpaQueryExecutionUnitTests {
|
||||
@Test
|
||||
void modifyingExecutionRejectsNonIntegerOrVoidReturnType() {
|
||||
|
||||
when(method.getReturnType()).thenReturn((Class) Long.class);
|
||||
when(method.getReturnType()).thenReturn((Class) BigDecimal.class);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ModifyingExecution(method, em));
|
||||
}
|
||||
|
||||
|
||||
@@ -300,10 +300,6 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
// DATAJPA-460
|
||||
List<User> deleteByLastname(String lastname);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from User u where u.emailAddress = ?1")
|
||||
User deleteAnnotatedQueryByEmailAddress(String username);
|
||||
|
||||
/**
|
||||
* Explicitly mapped to a procedure with name "plus1inout" in database.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user