Skip to content

Commit fb52b0b

Browse files
Evaluate entity name for StringAotQuery from EntityMetadata.
1 parent 2cd0ea7 commit fb52b0b

File tree

2 files changed

+87
-3
lines changed

2 files changed

+87
-3
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/aot/QueriesFactory.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
* Factory for {@link AotQueries}.
5858
*
5959
* @author Mark Paluch
60+
* @author Christoph Strobl
6061
* @since 4.0
6162
*/
6263
class QueriesFactory {
@@ -123,7 +124,7 @@ public AotQueries createQueries(RepositoryInformation repositoryInformation, Ret
123124
QueryEnhancerSelector selector, MergedAnnotation<Query> query, JpaQueryMethod queryMethod) {
124125

125126
if (query.isPresent() && StringUtils.hasText(query.getString("value"))) {
126-
return buildStringQuery(repositoryInformation.getDomainType(), returnedType, selector, query, queryMethod);
127+
return buildStringQuery(returnedType, selector, query, queryMethod);
127128
}
128129

129130
String queryName = queryMethod.getNamedQueryName();
@@ -138,10 +139,10 @@ private boolean hasNamedQuery(ReturnedType returnedType, String queryName) {
138139
return namedQueries.hasQuery(queryName) || getNamedQuery(returnedType, queryName) != null;
139140
}
140141

141-
private AotQueries buildStringQuery(Class<?> domainType, ReturnedType returnedType, QueryEnhancerSelector selector,
142+
private AotQueries buildStringQuery(ReturnedType returnedType, QueryEnhancerSelector selector,
142143
MergedAnnotation<Query> query, JpaQueryMethod queryMethod) {
143144

144-
UnaryOperator<String> operator = s -> s.replaceAll("#\\{#entityName}", domainType.getSimpleName());
145+
UnaryOperator<String> operator = s -> s.replaceAll("#\\{#entityName}", queryMethod.getEntityInformation().getEntityName());
145146
boolean isNative = query.getBoolean("nativeQuery");
146147
Function<String, DeclaredQuery> queryFunction = isNative ? DeclaredQuery::nativeQuery : DeclaredQuery::jpqlQuery;
147148
queryFunction = operator.andThen(queryFunction);
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.repository.aot;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.mockito.ArgumentMatchers.eq;
20+
import static org.mockito.Mockito.when;
21+
22+
import jakarta.persistence.EntityManagerFactory;
23+
24+
import org.assertj.core.api.InstanceOfAssertFactories;
25+
import org.junit.jupiter.api.BeforeEach;
26+
import org.junit.jupiter.api.Test;
27+
import org.mockito.Mockito;
28+
import org.springframework.core.annotation.MergedAnnotation;
29+
import org.springframework.data.jpa.repository.Query;
30+
import org.springframework.data.jpa.repository.query.JpaEntityMetadata;
31+
import org.springframework.data.jpa.repository.query.JpaQueryMethod;
32+
import org.springframework.data.jpa.repository.query.QueryEnhancerSelector;
33+
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
34+
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
35+
import org.springframework.data.repository.config.RepositoryConfigurationSource;
36+
import org.springframework.data.repository.core.RepositoryInformation;
37+
import org.springframework.data.repository.query.ReturnedType;
38+
39+
/**
40+
* Unit tests for {@link QueriesFactory}.
41+
*
42+
* @author Christoph Strobl
43+
*/
44+
class QueriesFactoryUnitTests {
45+
46+
QueriesFactory factory;
47+
48+
@BeforeEach
49+
void setUp() {
50+
51+
RepositoryConfigurationSource configSource = Mockito.mock(RepositoryConfigurationSource.class);
52+
EntityManagerFactory entityManagerFactory = Mockito.mock(EntityManagerFactory.class);
53+
54+
factory = new QueriesFactory(configSource, entityManagerFactory, this.getClass().getClassLoader());
55+
}
56+
57+
@Test // GH-4029
58+
@SuppressWarnings({ "rawtypes", "unchecked" })
59+
void stringQueryShouldResolveEntityNameFromJakartaAnnotationIfPresent() {
60+
61+
RepositoryInformation repositoryInformation = Mockito.mock(RepositoryInformation.class);
62+
JpaEntityMetadata<?> entityMetadata = Mockito.mock(JpaEntityInformation.class);
63+
when(entityMetadata.getEntityName()).thenReturn("CustomNamed");
64+
65+
MergedAnnotation<Query> queryAnnotation = Mockito.mock(MergedAnnotation.class);
66+
when(queryAnnotation.isPresent()).thenReturn(true);
67+
when(queryAnnotation.getString(eq("value"))).thenReturn("select t from #{#entityName} t");
68+
when(queryAnnotation.getBoolean(eq("nativeQuery"))).thenReturn(false);
69+
when(queryAnnotation.getString("countQuery")).thenReturn("select count(t) from #{#entityName} t");
70+
71+
JpaQueryMethod queryMethod = Mockito.mock(JpaQueryMethod.class);
72+
when(queryMethod.getEntityInformation()).thenReturn((JpaEntityMetadata) entityMetadata);
73+
74+
AotQueries generatedQueries = factory.createQueries(repositoryInformation,
75+
ReturnedType.of(Object.class, Object.class, new SpelAwareProxyProjectionFactory()),
76+
QueryEnhancerSelector.DEFAULT_SELECTOR, queryAnnotation, queryMethod);
77+
78+
assertThat(generatedQueries.result()).asInstanceOf(InstanceOfAssertFactories.type(StringAotQuery.class))
79+
.extracting(StringAotQuery::getQueryString).isEqualTo("select t from CustomNamed t");
80+
assertThat(generatedQueries.count()).asInstanceOf(InstanceOfAssertFactories.type(StringAotQuery.class))
81+
.extracting(StringAotQuery::getQueryString).isEqualTo("select count(t) from CustomNamed t");
82+
}
83+
}

0 commit comments

Comments
 (0)