3 changed files with 713 additions and 0 deletions
@ -0,0 +1,153 @@ |
|||||||
|
/* |
||||||
|
* 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.data.mongodb.repository; |
||||||
|
|
||||||
|
import org.junit.platform.commons.annotation.Testable; |
||||||
|
import org.openjdk.jmh.annotations.Benchmark; |
||||||
|
import org.openjdk.jmh.annotations.Level; |
||||||
|
import org.openjdk.jmh.annotations.Scope; |
||||||
|
import org.openjdk.jmh.annotations.Setup; |
||||||
|
import org.openjdk.jmh.annotations.State; |
||||||
|
import org.openjdk.jmh.annotations.TearDown; |
||||||
|
|
||||||
|
import org.springframework.aot.test.generate.TestGenerationContext; |
||||||
|
import org.springframework.core.test.tools.TestCompiler; |
||||||
|
import org.springframework.data.mongodb.core.MongoOperations; |
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate; |
||||||
|
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark; |
||||||
|
import org.springframework.data.mongodb.repository.aot.MongoRepositoryContributor; |
||||||
|
import org.springframework.data.mongodb.repository.aot.TestMongoAotRepositoryContext; |
||||||
|
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory; |
||||||
|
import org.springframework.data.mongodb.repository.support.QuerydslMongoPredicateExecutor; |
||||||
|
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; |
||||||
|
import org.springframework.data.projection.ProjectionFactory; |
||||||
|
import org.springframework.data.projection.SpelAwareProxyProjectionFactory; |
||||||
|
import org.springframework.data.repository.core.RepositoryMetadata; |
||||||
|
import org.springframework.data.repository.core.support.RepositoryComposition; |
||||||
|
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; |
||||||
|
import org.springframework.data.repository.core.support.RepositoryFragment; |
||||||
|
import org.springframework.data.repository.query.ValueExpressionDelegate; |
||||||
|
|
||||||
|
import com.mongodb.client.MongoClient; |
||||||
|
import com.mongodb.client.MongoClients; |
||||||
|
|
||||||
|
/** |
||||||
|
* Benchmark for AOT repositories. |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
*/ |
||||||
|
@Testable |
||||||
|
public class AotRepositoryBenchmark extends AbstractMicrobenchmark { |
||||||
|
|
||||||
|
@State(Scope.Benchmark) |
||||||
|
public static class BenchmarkParameters { |
||||||
|
|
||||||
|
public static Class<?> aot; |
||||||
|
public static TestMongoAotRepositoryContext repositoryContext = new TestMongoAotRepositoryContext( |
||||||
|
SmallerPersonRepository.class, |
||||||
|
RepositoryComposition.of(RepositoryFragment.structural(SimpleMongoRepository.class), |
||||||
|
RepositoryFragment.structural(QuerydslMongoPredicateExecutor.class))); |
||||||
|
|
||||||
|
MongoClient mongoClient; |
||||||
|
MongoTemplate mongoTemplate; |
||||||
|
RepositoryComposition.RepositoryFragments fragments; |
||||||
|
SmallerPersonRepository repositoryProxy; |
||||||
|
|
||||||
|
@Setup(Level.Trial) |
||||||
|
public void doSetup() { |
||||||
|
|
||||||
|
mongoClient = MongoClients.create(); |
||||||
|
mongoTemplate = new MongoTemplate(mongoClient, "jmh"); |
||||||
|
|
||||||
|
if (this.aot == null) { |
||||||
|
|
||||||
|
TestGenerationContext generationContext = new TestGenerationContext(PersonRepository.class); |
||||||
|
|
||||||
|
new MongoRepositoryContributor(repositoryContext).contribute(generationContext); |
||||||
|
|
||||||
|
TestCompiler.forSystem().withCompilerOptions("-parameters").with(generationContext).compile(compiled -> { |
||||||
|
|
||||||
|
try { |
||||||
|
this.aot = compiled.getClassLoader().loadClass(SmallerPersonRepository.class.getName() + "Impl__Aot"); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
RepositoryFactoryBeanSupport.FragmentCreationContext creationContext = getCreationContext(repositoryContext); |
||||||
|
fragments = RepositoryComposition.RepositoryFragments |
||||||
|
.just(aot.getConstructor(MongoOperations.class, RepositoryFactoryBeanSupport.FragmentCreationContext.class) |
||||||
|
.newInstance(mongoTemplate, creationContext)); |
||||||
|
|
||||||
|
this.repositoryProxy = createRepository(fragments); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private RepositoryFactoryBeanSupport.FragmentCreationContext getCreationContext( |
||||||
|
TestMongoAotRepositoryContext repositoryContext) { |
||||||
|
|
||||||
|
RepositoryFactoryBeanSupport.FragmentCreationContext creationContext = new RepositoryFactoryBeanSupport.FragmentCreationContext() { |
||||||
|
@Override |
||||||
|
public RepositoryMetadata getRepositoryMetadata() { |
||||||
|
return repositoryContext.getRepositoryInformation(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ValueExpressionDelegate getValueExpressionDelegate() { |
||||||
|
return ValueExpressionDelegate.create(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ProjectionFactory getProjectionFactory() { |
||||||
|
return new SpelAwareProxyProjectionFactory(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
return creationContext; |
||||||
|
} |
||||||
|
|
||||||
|
@TearDown(Level.Trial) |
||||||
|
public void doTearDown() { |
||||||
|
mongoClient.close(); |
||||||
|
} |
||||||
|
|
||||||
|
public SmallerPersonRepository createRepository(RepositoryComposition.RepositoryFragments fragments) { |
||||||
|
MongoRepositoryFactory repositoryFactory = new MongoRepositoryFactory(mongoTemplate); |
||||||
|
return repositoryFactory.getRepository(SmallerPersonRepository.class, fragments); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Benchmark |
||||||
|
public SmallerPersonRepository repositoryBootstrap(BenchmarkParameters parameters) { |
||||||
|
return parameters.createRepository(parameters.fragments); |
||||||
|
} |
||||||
|
|
||||||
|
@Benchmark |
||||||
|
public Object findDerived(BenchmarkParameters parameters) { |
||||||
|
return parameters.repositoryProxy.findByFirstname("foo"); |
||||||
|
} |
||||||
|
|
||||||
|
@Benchmark |
||||||
|
public Object findAnnotated(BenchmarkParameters parameters) { |
||||||
|
return parameters.repositoryProxy.findByThePersonsFirstname("foo"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,477 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2010-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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.data.mongodb.repository; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.UUID; |
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable; |
||||||
|
|
||||||
|
import org.springframework.data.domain.Limit; |
||||||
|
import org.springframework.data.domain.Page; |
||||||
|
import org.springframework.data.domain.Pageable; |
||||||
|
import org.springframework.data.domain.ScrollPosition; |
||||||
|
import org.springframework.data.domain.Slice; |
||||||
|
import org.springframework.data.domain.Sort; |
||||||
|
import org.springframework.data.domain.Window; |
||||||
|
import org.springframework.data.mongodb.core.aggregation.AggregationResults; |
||||||
|
import org.springframework.data.mongodb.core.query.UpdateDefinition; |
||||||
|
import org.springframework.data.mongodb.repository.Person.Sex; |
||||||
|
import org.springframework.data.querydsl.QuerydslPredicateExecutor; |
||||||
|
import org.springframework.data.repository.query.Param; |
||||||
|
|
||||||
|
/** |
||||||
|
* Sample repository managing {@link Person} entities. |
||||||
|
* |
||||||
|
* @author Oliver Gierke |
||||||
|
* @author Thomas Darimont |
||||||
|
* @author Christoph Strobl |
||||||
|
* @author Fırat KÜÇÜK |
||||||
|
* @author Mark Paluch |
||||||
|
*/ |
||||||
|
public interface SmallerPersonRepository extends MongoRepository<Person, String>, QuerydslPredicateExecutor<Person> { |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with the given lastname. |
||||||
|
* |
||||||
|
* @param lastname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByLastname(String lastname); |
||||||
|
|
||||||
|
List<Person> findByLastnameStartsWith(String prefix); |
||||||
|
|
||||||
|
List<Person> findByLastnameEndsWith(String postfix); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with the given lastname ordered by their firstname. |
||||||
|
* |
||||||
|
* @param lastname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByLastnameOrderByFirstnameAsc(String lastname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the {@link Person}s with the given firstname. Uses {@link Query} annotation to define the query to be |
||||||
|
* executed. |
||||||
|
* |
||||||
|
* @param firstname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Query(value = "{ 'lastname' : ?0 }", fields = "{ 'firstname': 1, 'lastname': 1}") |
||||||
|
List<Person> findByThePersonsLastname(String lastname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the {@link Person}s with the given firstname. Uses {@link Query} annotation to define the query to be |
||||||
|
* executed. |
||||||
|
* |
||||||
|
* @param firstname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Query(value = "{ 'firstname' : ?0 }", fields = "{ 'firstname': 1, 'lastname': 1}") |
||||||
|
List<Person> findByThePersonsFirstname(String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-871
|
||||||
|
@Query(value = "{ 'firstname' : ?0 }") |
||||||
|
Person[] findByThePersonsFirstnameAsArray(String firstname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with a firstname matching the given one (*-wildcard supported). |
||||||
|
* |
||||||
|
* @param firstname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByFirstnameLike(@Nullable String firstname); |
||||||
|
|
||||||
|
List<Person> findByFirstnameNotContains(String firstname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with a firstname not matching the given one (*-wildcard supported). |
||||||
|
* |
||||||
|
* @param firstname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByFirstnameNotLike(String firstname); |
||||||
|
|
||||||
|
List<Person> findByFirstnameLikeOrderByLastnameAsc(String firstname, Sort sort); |
||||||
|
|
||||||
|
List<Person> findBySkillsContains(List<String> skills); |
||||||
|
|
||||||
|
List<Person> findBySkillsNotContains(List<String> skills); |
||||||
|
|
||||||
|
@Query("{'age' : { '$lt' : ?0 } }") |
||||||
|
List<Person> findByAgeLessThan(int age, Sort sort); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a scroll of {@link Person}s with a lastname matching the given one (*-wildcards supported). |
||||||
|
* |
||||||
|
* @param lastname |
||||||
|
* @param scrollPosition |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Window<Person> findTop2ByLastnameLikeOrderByLastnameAscFirstnameAsc(String lastname, ScrollPosition scrollPosition); |
||||||
|
|
||||||
|
Window<Person> findByLastnameLikeOrderByLastnameAscFirstnameAsc(String lastname, ScrollPosition scrollPosition, |
||||||
|
Limit limit); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a scroll of {@link Person}s applying projections with a lastname matching the given one (*-wildcards |
||||||
|
* supported). |
||||||
|
* |
||||||
|
* @param lastname |
||||||
|
* @param pageable |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Window<PersonSummaryDto> findCursorProjectionByLastnameLike(String lastname, Pageable pageable); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a page of {@link Person}s with a lastname matching the given one (*-wildcards supported). |
||||||
|
* |
||||||
|
* @param lastname |
||||||
|
* @param pageable |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Page<Person> findByLastnameLike(String lastname, Pageable pageable); |
||||||
|
|
||||||
|
List<Person> findByLastnameLike(String lastname, Sort sort, Limit limit); |
||||||
|
|
||||||
|
@Query("{ 'lastname' : { '$regex' : '?0', '$options' : 'i'}}") |
||||||
|
Page<Person> findByLastnameLikeWithPageable(String lastname, Pageable pageable); |
||||||
|
|
||||||
|
List<Person> findByFirstname(String firstname); |
||||||
|
|
||||||
|
List<Person> findByLastnameIgnoreCaseIn(String... lastname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with a firstname contained in the given varargs. |
||||||
|
* |
||||||
|
* @param firstnames |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByFirstnameIn(String... firstnames); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with a firstname not contained in the given collection. |
||||||
|
* |
||||||
|
* @param firstnames |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByFirstnameNotIn(Collection<String> firstnames); |
||||||
|
|
||||||
|
List<Person> findByFirstnameAndLastname(String firstname, String lastname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with an age between the two given values. |
||||||
|
* |
||||||
|
* @param from |
||||||
|
* @param to |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByAgeBetween(int from, int to); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the {@link Person} with the given {@link Address} as shipping address. |
||||||
|
* |
||||||
|
* @param address |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Person findByShippingAddresses(Address address); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all {@link Person}s with the given {@link Address}. |
||||||
|
* |
||||||
|
* @param address |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<Person> findByAddress(Address address); |
||||||
|
|
||||||
|
List<Person> findByAddressZipCode(String zipCode); |
||||||
|
|
||||||
|
List<Person> findByLastnameLikeAndAgeBetween(String lastname, int from, int to); |
||||||
|
|
||||||
|
List<Person> findByAgeOrLastnameLikeAndFirstnameLike(int age, String lastname, String firstname); |
||||||
|
|
||||||
|
// TODO: List<Person> findByLocationNear(Point point);
|
||||||
|
|
||||||
|
// TODO: List<Person> findByLocationWithin(Circle circle);
|
||||||
|
|
||||||
|
// TODO: List<Person> findByLocationWithin(Box box);
|
||||||
|
|
||||||
|
// TODO: List<Person> findByLocationWithin(Polygon polygon);
|
||||||
|
|
||||||
|
List<Person> findBySex(Sex sex); |
||||||
|
|
||||||
|
List<Person> findBySex(Sex sex, Pageable pageable); |
||||||
|
|
||||||
|
// TODO: List<Person> findByNamedQuery(String firstname);
|
||||||
|
|
||||||
|
List<Person> findByCreator(User user); |
||||||
|
|
||||||
|
// DATAMONGO-425
|
||||||
|
List<Person> findByCreatedAtLessThan(Date date); |
||||||
|
|
||||||
|
// DATAMONGO-425
|
||||||
|
List<Person> findByCreatedAtGreaterThan(Date date); |
||||||
|
|
||||||
|
// DATAMONGO-425
|
||||||
|
@Query("{ 'createdAt' : { '$lt' : ?0 }}") |
||||||
|
List<Person> findByCreatedAtLessThanManually(Date date); |
||||||
|
|
||||||
|
// DATAMONGO-427
|
||||||
|
List<Person> findByCreatedAtBefore(Date date); |
||||||
|
|
||||||
|
// DATAMONGO-427
|
||||||
|
List<Person> findByCreatedAtAfter(Date date); |
||||||
|
|
||||||
|
// DATAMONGO-472
|
||||||
|
List<Person> findByLastnameNot(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-600
|
||||||
|
List<Person> findByCredentials(Credentials credentials); |
||||||
|
|
||||||
|
// DATAMONGO-636
|
||||||
|
long countByLastname(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-636
|
||||||
|
int countByFirstname(String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-636
|
||||||
|
@Query(value = "{ 'lastname' : ?0 }", count = true) |
||||||
|
long someCountQuery(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-1454
|
||||||
|
boolean existsByFirstname(String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-1454
|
||||||
|
@ExistsQuery(value = "{ 'lastname' : ?0 }") |
||||||
|
boolean someExistQuery(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-770
|
||||||
|
List<Person> findByFirstnameIgnoreCase(@Nullable String firstName); |
||||||
|
|
||||||
|
// DATAMONGO-770
|
||||||
|
List<Person> findByFirstnameNotIgnoreCase(String firstName); |
||||||
|
|
||||||
|
// DATAMONGO-770
|
||||||
|
List<Person> findByFirstnameStartingWithIgnoreCase(String firstName); |
||||||
|
|
||||||
|
// DATAMONGO-770
|
||||||
|
List<Person> findByFirstnameEndingWithIgnoreCase(String firstName); |
||||||
|
|
||||||
|
// DATAMONGO-770
|
||||||
|
List<Person> findByFirstnameContainingIgnoreCase(String firstName); |
||||||
|
|
||||||
|
// DATAMONGO-870
|
||||||
|
Slice<Person> findByAgeGreaterThan(int age, Pageable pageable); |
||||||
|
|
||||||
|
// DATAMONGO-821
|
||||||
|
@Query("{ creator : { $exists : true } }") |
||||||
|
Page<Person> findByHavingCreator(Pageable page); |
||||||
|
|
||||||
|
// DATAMONGO-566
|
||||||
|
List<Person> deleteByLastname(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-566
|
||||||
|
Long deletePersonByLastname(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-1997
|
||||||
|
Optional<Person> deleteOptionalByLastname(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-566
|
||||||
|
@Query(value = "{ 'lastname' : ?0 }", delete = true) |
||||||
|
List<Person> removeByLastnameUsingAnnotatedQuery(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-566
|
||||||
|
@Query(value = "{ 'lastname' : ?0 }", delete = true) |
||||||
|
Long removePersonByLastnameUsingAnnotatedQuery(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-893
|
||||||
|
Page<Person> findByAddressIn(List<Address> address, Pageable page); |
||||||
|
|
||||||
|
// DATAMONGO-745
|
||||||
|
@Query("{firstname:{$in:?0}, lastname:?1}") |
||||||
|
Page<Person> findByCustomQueryFirstnamesAndLastname(List<String> firstnames, String lastname, Pageable page); |
||||||
|
|
||||||
|
// DATAMONGO-745
|
||||||
|
@Query("{lastname:?0, 'address.street':{$in:?1}}") |
||||||
|
Page<Person> findByCustomQueryLastnameAndAddressStreetInList(String lastname, List<String> streetNames, |
||||||
|
Pageable page); |
||||||
|
|
||||||
|
// DATAMONGO-950
|
||||||
|
List<Person> findTop3ByLastnameStartingWith(String lastname); |
||||||
|
|
||||||
|
// DATAMONGO-950
|
||||||
|
Page<Person> findTop3ByLastnameStartingWith(String lastname, Pageable pageRequest); |
||||||
|
|
||||||
|
// DATAMONGO-1865
|
||||||
|
Person findFirstBy(); // limits to 1 result if more, just return the first one
|
||||||
|
|
||||||
|
// DATAMONGO-1865
|
||||||
|
Person findPersonByLastnameLike(String firstname); // single person, error if more than one
|
||||||
|
|
||||||
|
// DATAMONGO-1865
|
||||||
|
Optional<Person> findOptionalPersonByLastnameLike(String firstname); // optional still, error when more than one
|
||||||
|
|
||||||
|
// DATAMONGO-1030
|
||||||
|
PersonSummaryDto findSummaryByLastname(String lastname); |
||||||
|
|
||||||
|
PersonSummaryWithOptional findSummaryWithOptionalByLastname(String lastname); |
||||||
|
|
||||||
|
@Query("{ ?0 : ?1 }") |
||||||
|
List<Person> findByKeyValue(String key, String value); |
||||||
|
|
||||||
|
// DATAMONGO-1165
|
||||||
|
@Query("{ firstname : { $in : ?0 }}") |
||||||
|
Stream<Person> findByCustomQueryWithStreamingCursorByFirstnames(List<String> firstnames); |
||||||
|
|
||||||
|
// DATAMONGO-990
|
||||||
|
@Query("{ firstname : ?#{[0]}}") |
||||||
|
List<Person> findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly(String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-990
|
||||||
|
@Query("{ firstname : ?#{[0]}, email: ?#{principal.email} }") |
||||||
|
List<Person> findWithSpelByFirstnameAndCurrentUserWithCustomQuery(String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-990
|
||||||
|
@Query("{ firstname : :#{#firstname}}") |
||||||
|
List<Person> findWithSpelByFirstnameForSpELExpressionWithParameterVariableOnly(@Param("firstname") String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-1911
|
||||||
|
@Query("{ uniqueId: ?0}") |
||||||
|
Person findByUniqueId(UUID uniqueId); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the count of {@link Person} with the given firstname. Uses {@link CountQuery} annotation to define the |
||||||
|
* query to be executed. |
||||||
|
* |
||||||
|
* @param firstname |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@CountQuery("{ 'firstname' : ?0 }") // DATAMONGO-1539
|
||||||
|
long countByThePersonsFirstname(String firstname); |
||||||
|
|
||||||
|
/** |
||||||
|
* Deletes {@link Person} entities with the given firstname. Uses {@link DeleteQuery} annotation to define the query |
||||||
|
* to be executed. |
||||||
|
* |
||||||
|
* @param firstname |
||||||
|
*/ |
||||||
|
@DeleteQuery("{ 'firstname' : ?0 }") // DATAMONGO-1539
|
||||||
|
void deleteByThePersonsFirstname(String firstname); |
||||||
|
|
||||||
|
// DATAMONGO-1752
|
||||||
|
Iterable<PersonExcerpt> findOpenProjectionBy(); |
||||||
|
|
||||||
|
// DATAMONGO-1752
|
||||||
|
Iterable<PersonSummary> findClosedProjectionBy(); |
||||||
|
|
||||||
|
@Query(sort = "{ age : -1 }") |
||||||
|
List<Person> findByAgeGreaterThan(int age); |
||||||
|
|
||||||
|
@Query(sort = "{ age : -1 }") |
||||||
|
List<Person> findByAgeGreaterThan(int age, Sort sort); |
||||||
|
|
||||||
|
// TODO: List<Person> findByFirstnameRegex(Pattern pattern);
|
||||||
|
|
||||||
|
@Query(value = "{ 'id' : ?0 }", fields = "{ 'fans': { '$slice': [ ?1, ?2 ] } }") |
||||||
|
Person findWithSliceInProjection(String id, int skip, int limit); |
||||||
|
|
||||||
|
@Query(value = "{ 'id' : ?0 }", fields = "{ 'firstname': { '$toUpper': '$firstname' } }") |
||||||
|
Person findWithAggregationInProjection(String id); |
||||||
|
|
||||||
|
@Query(value = "{ 'shippingAddresses' : { '$elemMatch' : { 'city' : { '$eq' : 'lnz' } } } }", |
||||||
|
fields = "{ 'shippingAddresses.$': ?0 }") |
||||||
|
Person findWithArrayPositionInProjection(int position); |
||||||
|
|
||||||
|
@Query(value = "{ 'fans' : { '$elemMatch' : { '$ref' : 'user' } } }", fields = "{ 'fans.$': ?0 }") |
||||||
|
Person findWithArrayPositionInProjectionWithDbRef(int position); |
||||||
|
|
||||||
|
@Aggregation("{ '$project': { '_id' : '$lastname' } }") |
||||||
|
List<String> findAllLastnames(); |
||||||
|
|
||||||
|
@Aggregation("{ '$project': { '_id' : '$lastname' } }") |
||||||
|
Stream<String> findAllLastnamesAsStream(); |
||||||
|
|
||||||
|
@Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") |
||||||
|
Stream<PersonAggregate> groupStreamByLastnameAnd(String property); |
||||||
|
|
||||||
|
@Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") |
||||||
|
List<PersonAggregate> groupByLastnameAnd(String property); |
||||||
|
|
||||||
|
@Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") |
||||||
|
Slice<PersonAggregate> groupByLastnameAndAsSlice(String property, Pageable pageable); |
||||||
|
|
||||||
|
@Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") |
||||||
|
List<PersonAggregate> groupByLastnameAnd(String property, Sort sort); |
||||||
|
|
||||||
|
@Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") |
||||||
|
List<PersonAggregate> groupByLastnameAnd(String property, Pageable page); |
||||||
|
|
||||||
|
@Aggregation(pipeline = "{ '$group' : { '_id' : null, 'total' : { $sum: '$age' } } }") |
||||||
|
int sumAge(); |
||||||
|
|
||||||
|
@Aggregation(pipeline = "{ '$group' : { '_id' : null, 'total' : { $sum: '$age' } } }") |
||||||
|
AggregationResults<org.bson.Document> sumAgeAndReturnAggregationResultWrapper(); |
||||||
|
|
||||||
|
@Aggregation(pipeline = "{ '$group' : { '_id' : null, 'total' : { $sum: '$age' } } }") |
||||||
|
AggregationResults<SumAge> sumAgeAndReturnAggregationResultWrapperWithConcreteType(); |
||||||
|
|
||||||
|
@Aggregation({ "{ '$match' : { 'lastname' : 'Matthews'} }", |
||||||
|
"{ '$project': { _id : 0, firstname : 1, lastname : 1 } }" }) |
||||||
|
Iterable<PersonSummary> findAggregatedClosedInterfaceProjectionBy(); |
||||||
|
|
||||||
|
@Query(value = "{_id:?0}") |
||||||
|
Optional<org.bson.Document> findDocumentById(String id); |
||||||
|
|
||||||
|
@Query(value = "{ 'firstname' : ?0, 'lastname' : ?1, 'email' : ?2 , 'age' : ?3, 'sex' : ?4, " |
||||||
|
+ "'createdAt' : ?5, 'skills' : ?6, 'address.street' : ?7, 'address.zipCode' : ?8, " //
|
||||||
|
+ "'address.city' : ?9, 'uniqueId' : ?10, 'credentials.username' : ?11, 'credentials.password' : ?12 }") |
||||||
|
Person findPersonByManyArguments(String firstname, String lastname, String email, Integer age, Sex sex, |
||||||
|
Date createdAt, List<String> skills, String street, String zipCode, //
|
||||||
|
String city, UUID uniqueId, String username, String password); |
||||||
|
|
||||||
|
List<Person> findByUnwrappedUserUsername(String username); |
||||||
|
|
||||||
|
List<Person> findByUnwrappedUser(User user); |
||||||
|
|
||||||
|
int findAndUpdateViaMethodArgAllByLastname(String lastname, UpdateDefinition update); |
||||||
|
|
||||||
|
@Update("{ '$inc' : { 'visits' : ?1 } }") |
||||||
|
int findAndIncrementVisitsByLastname(String lastname, int increment); |
||||||
|
|
||||||
|
@Query("{ 'lastname' : ?0 }") |
||||||
|
@Update("{ '$inc' : { 'visits' : ?1 } }") |
||||||
|
int updateAllByLastname(String lastname, int increment); |
||||||
|
|
||||||
|
@Update(pipeline = { "{ '$set' : { 'visits' : { '$add' : [ '$visits', ?1 ] } } }" }) |
||||||
|
void findAndIncrementVisitsViaPipelineByLastname(String lastname, int increment); |
||||||
|
|
||||||
|
@Update("{ '$inc' : { 'visits' : ?#{[1]} } }") |
||||||
|
int findAndIncrementVisitsUsingSpELByLastname(String lastname, int increment); |
||||||
|
|
||||||
|
@Update("{ '$push' : { 'shippingAddresses' : ?1 } }") |
||||||
|
int findAndPushShippingAddressByEmail(String email, Address address); |
||||||
|
|
||||||
|
@Query("{ 'age' : null }") |
||||||
|
Person findByQueryWithNullEqualityCheck(); |
||||||
|
|
||||||
|
List<Person> findBySpiritAnimal(User user); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.data.mongodb.repository; |
||||||
|
|
||||||
|
import org.junit.platform.commons.annotation.Testable; |
||||||
|
import org.openjdk.jmh.annotations.Benchmark; |
||||||
|
import org.openjdk.jmh.annotations.Level; |
||||||
|
import org.openjdk.jmh.annotations.Scope; |
||||||
|
import org.openjdk.jmh.annotations.Setup; |
||||||
|
import org.openjdk.jmh.annotations.State; |
||||||
|
import org.openjdk.jmh.annotations.TearDown; |
||||||
|
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate; |
||||||
|
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark; |
||||||
|
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory; |
||||||
|
|
||||||
|
import com.mongodb.client.MongoClient; |
||||||
|
import com.mongodb.client.MongoClients; |
||||||
|
|
||||||
|
/** |
||||||
|
* Benchmark for AOT repositories. |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
*/ |
||||||
|
@Testable |
||||||
|
public class SmallerRepositoryBenchmark extends AbstractMicrobenchmark { |
||||||
|
|
||||||
|
@State(Scope.Benchmark) |
||||||
|
public static class BenchmarkParameters { |
||||||
|
|
||||||
|
MongoClient mongoClient; |
||||||
|
MongoTemplate mongoTemplate; |
||||||
|
SmallerPersonRepository repositoryProxy; |
||||||
|
|
||||||
|
@Setup(Level.Trial) |
||||||
|
public void doSetup() { |
||||||
|
|
||||||
|
mongoClient = MongoClients.create(); |
||||||
|
mongoTemplate = new MongoTemplate(mongoClient, "jmh"); |
||||||
|
repositoryProxy = createRepository(); |
||||||
|
} |
||||||
|
|
||||||
|
@TearDown(Level.Trial) |
||||||
|
public void doTearDown() { |
||||||
|
mongoClient.close(); |
||||||
|
} |
||||||
|
|
||||||
|
public SmallerPersonRepository createRepository() { |
||||||
|
MongoRepositoryFactory repositoryFactory = new MongoRepositoryFactory(mongoTemplate); |
||||||
|
return repositoryFactory.getRepository(SmallerPersonRepository.class); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Benchmark |
||||||
|
public SmallerPersonRepository repositoryBootstrap(BenchmarkParameters parameters) { |
||||||
|
return parameters.createRepository(); |
||||||
|
} |
||||||
|
|
||||||
|
@Benchmark |
||||||
|
public Object findDerived(BenchmarkParameters parameters) { |
||||||
|
return parameters.repositoryProxy.findByFirstname("foo"); |
||||||
|
} |
||||||
|
|
||||||
|
@Benchmark |
||||||
|
public Object findAnnotated(BenchmarkParameters parameters) { |
||||||
|
return parameters.repositoryProxy.findByThePersonsFirstname("foo"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue