diff --git a/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/AotRepositoryBenchmark.java b/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/AotRepositoryBenchmark.java new file mode 100644 index 000000000..ba9da66da --- /dev/null +++ b/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/AotRepositoryBenchmark.java @@ -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"); + } + +} diff --git a/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/SmallerPersonRepository.java b/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/SmallerPersonRepository.java new file mode 100644 index 000000000..bc3868e05 --- /dev/null +++ b/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/SmallerPersonRepository.java @@ -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, QuerydslPredicateExecutor { + + /** + * Returns all {@link Person}s with the given lastname. + * + * @param lastname + * @return + */ + List findByLastname(String lastname); + + List findByLastnameStartsWith(String prefix); + + List findByLastnameEndsWith(String postfix); + + /** + * Returns all {@link Person}s with the given lastname ordered by their firstname. + * + * @param lastname + * @return + */ + List 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 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 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 findByFirstnameLike(@Nullable String firstname); + + List findByFirstnameNotContains(String firstname); + + /** + * Returns all {@link Person}s with a firstname not matching the given one (*-wildcard supported). + * + * @param firstname + * @return + */ + List findByFirstnameNotLike(String firstname); + + List findByFirstnameLikeOrderByLastnameAsc(String firstname, Sort sort); + + List findBySkillsContains(List skills); + + List findBySkillsNotContains(List skills); + + @Query("{'age' : { '$lt' : ?0 } }") + List 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 findTop2ByLastnameLikeOrderByLastnameAscFirstnameAsc(String lastname, ScrollPosition scrollPosition); + + Window 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 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 findByLastnameLike(String lastname, Pageable pageable); + + List findByLastnameLike(String lastname, Sort sort, Limit limit); + + @Query("{ 'lastname' : { '$regex' : '?0', '$options' : 'i'}}") + Page findByLastnameLikeWithPageable(String lastname, Pageable pageable); + + List findByFirstname(String firstname); + + List findByLastnameIgnoreCaseIn(String... lastname); + + /** + * Returns all {@link Person}s with a firstname contained in the given varargs. + * + * @param firstnames + * @return + */ + List findByFirstnameIn(String... firstnames); + + /** + * Returns all {@link Person}s with a firstname not contained in the given collection. + * + * @param firstnames + * @return + */ + List findByFirstnameNotIn(Collection firstnames); + + List findByFirstnameAndLastname(String firstname, String lastname); + + /** + * Returns all {@link Person}s with an age between the two given values. + * + * @param from + * @param to + * @return + */ + List 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 findByAddress(Address address); + + List findByAddressZipCode(String zipCode); + + List findByLastnameLikeAndAgeBetween(String lastname, int from, int to); + + List findByAgeOrLastnameLikeAndFirstnameLike(int age, String lastname, String firstname); + + // TODO: List findByLocationNear(Point point); + + // TODO: List findByLocationWithin(Circle circle); + + // TODO: List findByLocationWithin(Box box); + + // TODO: List findByLocationWithin(Polygon polygon); + + List findBySex(Sex sex); + + List findBySex(Sex sex, Pageable pageable); + + // TODO: List findByNamedQuery(String firstname); + + List findByCreator(User user); + + // DATAMONGO-425 + List findByCreatedAtLessThan(Date date); + + // DATAMONGO-425 + List findByCreatedAtGreaterThan(Date date); + + // DATAMONGO-425 + @Query("{ 'createdAt' : { '$lt' : ?0 }}") + List findByCreatedAtLessThanManually(Date date); + + // DATAMONGO-427 + List findByCreatedAtBefore(Date date); + + // DATAMONGO-427 + List findByCreatedAtAfter(Date date); + + // DATAMONGO-472 + List findByLastnameNot(String lastname); + + // DATAMONGO-600 + List 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 findByFirstnameIgnoreCase(@Nullable String firstName); + + // DATAMONGO-770 + List findByFirstnameNotIgnoreCase(String firstName); + + // DATAMONGO-770 + List findByFirstnameStartingWithIgnoreCase(String firstName); + + // DATAMONGO-770 + List findByFirstnameEndingWithIgnoreCase(String firstName); + + // DATAMONGO-770 + List findByFirstnameContainingIgnoreCase(String firstName); + + // DATAMONGO-870 + Slice findByAgeGreaterThan(int age, Pageable pageable); + + // DATAMONGO-821 + @Query("{ creator : { $exists : true } }") + Page findByHavingCreator(Pageable page); + + // DATAMONGO-566 + List deleteByLastname(String lastname); + + // DATAMONGO-566 + Long deletePersonByLastname(String lastname); + + // DATAMONGO-1997 + Optional deleteOptionalByLastname(String lastname); + + // DATAMONGO-566 + @Query(value = "{ 'lastname' : ?0 }", delete = true) + List removeByLastnameUsingAnnotatedQuery(String lastname); + + // DATAMONGO-566 + @Query(value = "{ 'lastname' : ?0 }", delete = true) + Long removePersonByLastnameUsingAnnotatedQuery(String lastname); + + // DATAMONGO-893 + Page findByAddressIn(List
address, Pageable page); + + // DATAMONGO-745 + @Query("{firstname:{$in:?0}, lastname:?1}") + Page findByCustomQueryFirstnamesAndLastname(List firstnames, String lastname, Pageable page); + + // DATAMONGO-745 + @Query("{lastname:?0, 'address.street':{$in:?1}}") + Page findByCustomQueryLastnameAndAddressStreetInList(String lastname, List streetNames, + Pageable page); + + // DATAMONGO-950 + List findTop3ByLastnameStartingWith(String lastname); + + // DATAMONGO-950 + Page 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 findOptionalPersonByLastnameLike(String firstname); // optional still, error when more than one + + // DATAMONGO-1030 + PersonSummaryDto findSummaryByLastname(String lastname); + + PersonSummaryWithOptional findSummaryWithOptionalByLastname(String lastname); + + @Query("{ ?0 : ?1 }") + List findByKeyValue(String key, String value); + + // DATAMONGO-1165 + @Query("{ firstname : { $in : ?0 }}") + Stream findByCustomQueryWithStreamingCursorByFirstnames(List firstnames); + + // DATAMONGO-990 + @Query("{ firstname : ?#{[0]}}") + List findWithSpelByFirstnameForSpELExpressionWithParameterIndexOnly(String firstname); + + // DATAMONGO-990 + @Query("{ firstname : ?#{[0]}, email: ?#{principal.email} }") + List findWithSpelByFirstnameAndCurrentUserWithCustomQuery(String firstname); + + // DATAMONGO-990 + @Query("{ firstname : :#{#firstname}}") + List 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 findOpenProjectionBy(); + + // DATAMONGO-1752 + Iterable findClosedProjectionBy(); + + @Query(sort = "{ age : -1 }") + List findByAgeGreaterThan(int age); + + @Query(sort = "{ age : -1 }") + List findByAgeGreaterThan(int age, Sort sort); + + // TODO: List 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 findAllLastnames(); + + @Aggregation("{ '$project': { '_id' : '$lastname' } }") + Stream findAllLastnamesAsStream(); + + @Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") + Stream groupStreamByLastnameAnd(String property); + + @Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") + List groupByLastnameAnd(String property); + + @Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") + Slice groupByLastnameAndAsSlice(String property, Pageable pageable); + + @Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") + List groupByLastnameAnd(String property, Sort sort); + + @Aggregation("{ '$group': { '_id' : '$lastname', names : { $addToSet : '$?0' } } }") + List groupByLastnameAnd(String property, Pageable page); + + @Aggregation(pipeline = "{ '$group' : { '_id' : null, 'total' : { $sum: '$age' } } }") + int sumAge(); + + @Aggregation(pipeline = "{ '$group' : { '_id' : null, 'total' : { $sum: '$age' } } }") + AggregationResults sumAgeAndReturnAggregationResultWrapper(); + + @Aggregation(pipeline = "{ '$group' : { '_id' : null, 'total' : { $sum: '$age' } } }") + AggregationResults sumAgeAndReturnAggregationResultWrapperWithConcreteType(); + + @Aggregation({ "{ '$match' : { 'lastname' : 'Matthews'} }", + "{ '$project': { _id : 0, firstname : 1, lastname : 1 } }" }) + Iterable findAggregatedClosedInterfaceProjectionBy(); + + @Query(value = "{_id:?0}") + Optional 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 skills, String street, String zipCode, // + String city, UUID uniqueId, String username, String password); + + List findByUnwrappedUserUsername(String username); + + List 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 findBySpiritAnimal(User user); + +} diff --git a/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/SmallerRepositoryBenchmark.java b/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/SmallerRepositoryBenchmark.java new file mode 100644 index 000000000..f461a22d3 --- /dev/null +++ b/spring-data-mongodb/src/jmh/java/org/springframework/data/mongodb/repository/SmallerRepositoryBenchmark.java @@ -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"); + } + +}