Skip to content

Commit 394c807

Browse files
Add support for MongoDB AOT Repositories.
Initial Support for generating repository source code at build time. Closes: #4939
1 parent 4244a88 commit 394c807

23 files changed

+2922
-16
lines changed

spring-data-mongodb/pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,12 @@
288288
<scope>test</scope>
289289
</dependency>
290290

291+
<dependency>
292+
<groupId>org.springframework</groupId>
293+
<artifactId>spring-core-test</artifactId>
294+
<scope>test</scope>
295+
</dependency>
296+
291297
<!-- Kotlin extension -->
292298
<dependency>
293299
<groupId>org.jetbrains.kotlin</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* Copyright 2025 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.mongodb.aot.generated;
17+
18+
import java.util.Iterator;
19+
import java.util.List;
20+
import java.util.stream.Collectors;
21+
import java.util.stream.IntStream;
22+
23+
import org.bson.conversions.Bson;
24+
import org.springframework.data.domain.Pageable;
25+
import org.springframework.data.domain.Range;
26+
import org.springframework.data.domain.ScrollPosition;
27+
import org.springframework.data.domain.Sort;
28+
import org.springframework.data.geo.Distance;
29+
import org.springframework.data.geo.Point;
30+
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
31+
import org.springframework.data.mongodb.core.convert.MongoWriter;
32+
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
33+
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
34+
import org.springframework.data.mongodb.core.query.Collation;
35+
import org.springframework.data.mongodb.core.query.CriteriaDefinition.Placeholder;
36+
import org.springframework.data.mongodb.core.query.Query;
37+
import org.springframework.data.mongodb.core.query.TextCriteria;
38+
import org.springframework.data.mongodb.core.query.UpdateDefinition;
39+
import org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor;
40+
import org.springframework.data.mongodb.repository.query.MongoParameterAccessor;
41+
import org.springframework.data.mongodb.repository.query.MongoQueryCreator;
42+
import org.springframework.data.repository.query.parser.PartTree;
43+
import org.springframework.data.util.TypeInformation;
44+
import org.springframework.lang.Nullable;
45+
46+
import com.mongodb.DBRef;
47+
48+
/**
49+
* @author Christoph Strobl
50+
* @since 2025/01
51+
*/
52+
public class AotQueryCreator {
53+
54+
private MongoMappingContext mappingContext;
55+
56+
public AotQueryCreator() {
57+
58+
MongoMappingContext mongoMappingContext = new MongoMappingContext();
59+
mongoMappingContext.setSimpleTypeHolder(
60+
MongoCustomConversions.create((cfg) -> cfg.useNativeDriverJavaTimeCodecs()).getSimpleTypeHolder());
61+
mongoMappingContext.setAutoIndexCreation(false);
62+
mongoMappingContext.afterPropertiesSet();
63+
64+
this.mappingContext = mongoMappingContext;
65+
}
66+
67+
StringQuery createQuery(PartTree partTree, int parameterCount) {
68+
69+
Query query = new MongoQueryCreator(partTree,
70+
new PlaceholderConvertingParameterAccessor(new PlaceholderParameterAccessor(parameterCount)), mappingContext)
71+
.createQuery();
72+
73+
if(partTree.isLimiting()) {
74+
query.limit(partTree.getMaxResults());
75+
}
76+
return new StringQuery(query);
77+
}
78+
79+
static class PlaceholderConvertingParameterAccessor extends ConvertingParameterAccessor {
80+
81+
/**
82+
* Creates a new {@link ConvertingParameterAccessor} with the given {@link MongoWriter} and delegate.
83+
*
84+
* @param delegate must not be {@literal null}.
85+
*/
86+
public PlaceholderConvertingParameterAccessor(PlaceholderParameterAccessor delegate) {
87+
super(PlaceholderWriter.INSTANCE, delegate);
88+
}
89+
}
90+
91+
enum PlaceholderWriter implements MongoWriter<Object> {
92+
93+
INSTANCE;
94+
95+
@Nullable
96+
@Override
97+
public Object convertToMongoType(@Nullable Object obj, @Nullable TypeInformation<?> typeInformation) {
98+
return obj instanceof Placeholder p ? p.getValue() : obj;
99+
}
100+
101+
@Override
102+
public DBRef toDBRef(Object object, @Nullable MongoPersistentProperty referringProperty) {
103+
return null;
104+
}
105+
106+
@Override
107+
public void write(Object source, Bson sink) {
108+
109+
}
110+
}
111+
112+
static class PlaceholderParameterAccessor implements MongoParameterAccessor {
113+
114+
private final List<Placeholder> placeholders;
115+
116+
public PlaceholderParameterAccessor(int parameterCount) {
117+
if (parameterCount == 0) {
118+
placeholders = List.of();
119+
} else {
120+
placeholders = IntStream.range(0, parameterCount).mapToObj(it -> new Placeholder("?" + it))
121+
.collect(Collectors.toList());
122+
}
123+
}
124+
125+
@Override
126+
public Range<Distance> getDistanceRange() {
127+
return null;
128+
}
129+
130+
@Nullable
131+
@Override
132+
public Point getGeoNearLocation() {
133+
return null;
134+
}
135+
136+
@Nullable
137+
@Override
138+
public TextCriteria getFullText() {
139+
return null;
140+
}
141+
142+
@Nullable
143+
@Override
144+
public Collation getCollation() {
145+
return null;
146+
}
147+
148+
@Override
149+
public Object[] getValues() {
150+
return placeholders.toArray();
151+
}
152+
153+
@Nullable
154+
@Override
155+
public UpdateDefinition getUpdate() {
156+
return null;
157+
}
158+
159+
@Nullable
160+
@Override
161+
public ScrollPosition getScrollPosition() {
162+
return null;
163+
}
164+
165+
@Override
166+
public Pageable getPageable() {
167+
return null;
168+
}
169+
170+
@Override
171+
public Sort getSort() {
172+
return null;
173+
}
174+
175+
@Nullable
176+
@Override
177+
public Class<?> findDynamicProjection() {
178+
return null;
179+
}
180+
181+
@Nullable
182+
@Override
183+
public Object getBindableValue(int index) {
184+
return placeholders.get(index).getValue();
185+
}
186+
187+
@Override
188+
public boolean hasBindableNullValue() {
189+
return false;
190+
}
191+
192+
@Override
193+
@SuppressWarnings({ "unchecked", "rawtypes" })
194+
public Iterator<Object> iterator() {
195+
return ((List) placeholders).iterator();
196+
}
197+
}
198+
199+
}

0 commit comments

Comments
 (0)