2

I try to implement a JPA custom repository.

I have a filter object like this:

public class FilterPatient {
    private String surname;
    private String name;
    private String cf;

    ... and so on
}

From front end I create an instance of FilterPatient based on user input.

So, user, for example, can value surname and cf properties or surname and name, and so on

I want to implement a custom repository as follow:

PatientRepository extends JpaRepository<Patient, Long> {
    List<Patient> findBySurname(String surname);

    List<Patient> findByName(String name);

    List<Patient> findByCf(String cf);

    // custom methods:
    @Query("select p from Patient p where p.name = :name
        and p.surname = :surname")
    List<Patient> findByNameAndSurname(@Param("name") String name,
          @Param("surname") String surname);

    ... and so on
}

Question:

Based on user input I must execute a different query, so how I manage the repository? I must write query methods to cover different combinations of input field and in the service I must write the logic about method repository call? Or I can parametrize better my custom method query?

Other infos:

Without spring-data normally, I define a DAO method with input parameter FilterPatient, so I build a query based on parameter not null and then I substitute parameter with query.setString method. In this way I write one generic method, is it possible with Spring-data and JPA repositories?

EDIT

Sample query by user

SELECT FROM Patient p WHERE p.name = :name
AND p.surname = :surname
AND p.cf = :cf

and other possible configuration, for example, in cf property of FilterPatient IS NULL, the query will become:

SELECT FROM Patient p WHERE p.name = :name
AND p.surname = :surname
4
  • Do you want to invoke a query which filter data according to user input, like equals, less than, greater than..? or else by comparing with different properties? I think if that the case jpa criteria query will be helpful. Can you put a sample user query? Commented Oct 22, 2016 at 6:03
  • The first you have written Commented Oct 22, 2016 at 8:23
  • you can do it with spring data JPA Specification, this tutorial may help you. Commented Oct 22, 2016 at 8:32
  • While you have accepted an answer,, you can actually easily achieve your requirement using the suggestion of @Ruwanka Madhushan . See my answer which expands on this Commented Oct 22, 2016 at 14:05

2 Answers 2

4

You have a lot of built-in ways to create custom queries, for example findByNameAndSurname will work without the @Query annotation..

enter image description here

http://docs.spring.io/spring-data/jpa/docs/1.3.0.RELEASE/reference/html/jpa.repositories.html#jpa.query-methods

Sign up to request clarification or add additional context in comments.

7 Comments

Dear, thanks, but, my question is a bit different. I have an object where user decides input, so I must write different method in repository and deicde in service how call based on input? If so, this way is more complex than the old way I used (DAO with only one method)
I suggest to use the repository as simple as you can, only access/modify data, and have a service layer for your custom logic.
So, I must write (in my example I have 3 properties) I must write 7 repository methods and in the service I decide which of 7 methods I must call?
You can do both ways, create a custom query based on filters or have several method in a repository and use them in service.. writing methods in a repository is a one liner.. so I would prefer that option, but is just my opinion
Ok, thanks. For me your answer is OK, Spring data NO :D
|
2

What you are looking for is the Specification pattern which is discussed in relation to Spring Data JPA at the following:

https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

and which notes with reference to having a query method per query:

Although this approach is really convenient (you don’t even have to write a single line of implementation code to get the queries executed) it has two drawbacks: first, the number of query methods might grow for larger applications because of - and that’s the second point - the queries define a fixed set of criterias. To avoid these two drawbacks, wouldn’t it be cool if you could come up with a set of atomic predicates that you could combine dynamically to build your query?

You can implement the Specification pattern using either the JPA criteria API or using QueryDSL. Using the latter this is as easy as having your repository extend the following interface:

http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/querydsl/QueryDslPredicateExecutor.html

and adding support for Querydsl to your project. For a Maven project you simply need to add the configuration below to your POM. The plugin will auto generate the Query classes required to construct the predicates and you can then call the following methods of your Repository with any combination of parameters:

Iterable<T> findAll(com.querydsl.core.types.OrderSpecifier<?>... orders)
Iterable<T> findAll(com.querydsl.core.types.Predicate predicate)
Iterable<T> findAll(com.querydsl.core.types.Predicate predicate, com.querydsl.core.types.OrderSpecifier<?>... orders)
Page<T> findAll(com.querydsl.core.types.Predicate predicate, Pageable pageable)
Iterable<T> findAll(com.querydsl.core.types.Predicate predicate, Sort sort)
T   findOne(com.querydsl.core.types.Predicate predicate)

With this approach then your PatientRepository becomes simply:

PatientRepository extends JpaRepository<Patient, Long>, QueryDslLPredicateExecutor<Patient> {
   // no query methods needed
}

Note that the Spring Data Gosling release also added support for automatically binding HTTP params to a QueryDSL Predicate so you could also remove your Filter and have Spring Data handle everything end-to-end.

https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#querydsl-web-support

There are some examples here showing 1 query method being called with various parameters:

https://stackoverflow.com/a/26450224/1356423

Maven Setup:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    .....

    <properties>
        <querydsl.version>4.1.3</querydsl.version>
    </properties>

    <dependencies>

        .....

        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-jpa</artifactId>
            <version>${querydsl.version}</version>
        </dependency>
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>${querydsl.version}</version>
        </dependency>
    </dependencies>

    <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>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

1 Comment

thanks for your explanation. The context is more clear now. I prefer the old style query but I try to implement this to grow my knowledge. Have a nice day

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.