Spring数据JPA自定义存储库,如何应用逻辑

时间:2016-10-22 00:58:36

标签: java jpa spring-data spring-data-jpa

我尝试实现JPA自定义存储库。

我有一个像这样的过滤器对象:

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

    ... and so on
}

从前端开始,我根据用户输入创建了一个FilterPatient实例。

因此,例如,用户可以对姓氏和cf属性或姓氏和姓名进行评估,等等

我想实现一个自定义存储库,如下所示:

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
}

问题:

根据用户输入,我必须执行不同的查询,那么我如何管理存储库?我必须编写查询方法来覆盖输入字段的不同组合,在服务中我必须编写关于方法存储库调用的逻辑吗?或者我可以更好地参数化我的自定义方法查询?

其他信息:

通常没有spring-data,我用输入参数FilterPatient定义一个DAO方法,所以我基于参数not null建立一个查询,然后用query.setString方法替换参数。通过这种方式,我编写了一个通用方法,是否可以使用Spring-data和JPA存储库?

修改

用户的示例查询

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

和其他可能的配置,例如,在FilterPatient IS NULL的cf属性中,查询将变为:

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

2 个答案:

答案 0 :(得分:3)

您有很多内置方法可以创建自定义查询,例如findByNameAndSurname可以在没有@Query注释的情况下工作。

enter image description here

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

答案 1 :(得分:2)

您正在寻找的是以下与Spring Data JPA相关的规范模式:

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

以及每个查询都有一个查询方法的注释:

  

虽然这种方法非常方便(你甚至不需要   编写一行实现代码来获取查询   它有两个缺点:第一,查询方法的数量   由于 - 而且这是第二个,因此可能会为更大的应用程序而增长   point - 查询定义了一组固定的标准。避免这些   两个缺点,如果你想出一套可能不会很酷   原子谓词,你可以动态组合来构建你的   查询?

您可以使用JPA条件API或使用QueryDSL来实现规范模式。使用后者就像让您的存储库扩展以下接口一样简单:

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

并将Querydsl支持添加到您的项目中。对于Maven项目,您只需将下面的配置添加到POM中。该插件将自动生成构造谓词所需的Query类,然后您可以使用任何参数组合调用Repository的以下方法:

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)

通过这种方法,您的PatientRepository变得简单:

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

请注意,Spring Data Gosling版本还添加了对自动将HTTP参数绑定到QueryDSL谓词的支持,因此您也可以删除过滤器并让Spring Data端到端地处理所有内容。

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

此处有一些示例显示了使用各种参数调用的1个查询方法:

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

Maven设置:

<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>