springspring-dataspring-data-mongodbdynamicquerydynamic-queries

Spring Data MongoDB Repository - JPA Specifications like


Is there something like JPA Specifications for Spring Data MongoDB Repositories?

If not, how can I make dynamic queries with repositories?

A classic scenario could be a search form with optional fields that the user will fill.


Solution

  • I found myself a way.

    The trick can be done using QueryDSL, in the following way:

    First, add the QueryDSL dependencies:

    <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-mongodb</artifactId>
        <version>${querydsl-mongo.version}</version>
    </dependency>
    
    <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>${querydsl-mongo.version}</version>
    </dependency>
    

    Then, configure the plugin in order to create Metamodels classes (their names will be the same of the documents with the letter Q as prefix: eg. QUser):

        <build>
            <plugins>
                ....
                <plugin>
                    <groupId>com.mysema.maven</groupId>
                    <artifactId>apt-maven-plugin</artifactId>
                    <version>1.1.3</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>process</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>target/generated-sources/java</outputDirectory>
                                <processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    

    Note the processor class: it's not the QueryDSL default one com.mysema.query.apt.morphia.MorphiaAnnotationProcessor, but the Spring Data MongoDB one org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor:

    Spring Data Mongo provides a custom APT processor to generate the Metamodels instead of the one provided in QueryDSL, it will scan the Spring specific @Document instead of the Morphia specific annotations.

    Now we can make our repository interface extending QueryDslPredicateExecutor<T>:

    public interface UserRepository extends MongoRepository<User, String>, QueryDslPredicateExecutor<User>,
            QuerydslBinderCustomizer<QUser> {
    }
    

    We can now define Predicates when querying the repository:

    QUser user = QUser.user;            
    BooleanExpression predicate = user.name.containsIgnoreCase("John");         
    userRepository.findAll(predicate);
    

    QuerydslBinderCustomizer helps you to define the binding of the Document's properties (see Spring documentation for further help).