基于params的Spring数据动态@Query可能吗?

时间:2017-02-01 18:13:22

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

我最近从JEE切换到Spring Boot,到目前为止我很喜欢它。 但我遇到了一个小问题。我有这个方法来获取过去看起来像这样的惰性引用:

public Foo getParentWithChildren(long id, boolean isFetchChild, boolean isFetchPets) {
    StringBuilder sql = new StringBuilder();
    sql.append("select DISTINCT(p) from Parent p");
    if(isFetchChild) {
        sql.append(" left join p.child c");
    } if(isFetchPets) {
        sql.append(" left join p.pets pts");
    } 

    sql.append(" where p.id=:id");

    TypedQuery<Foo> query = em.createQuery(sql.toString(), Foo.class);
    query.setParameter("id", id);
    return query.getSingleResult();
}

现在有了spring数据和他们非常棒的接口,我想在界面上使用@Query注释做一些类似的事情而不必编写自定义实现。但是只使用界面可以做类似的事情。

下面的示例显然不起作用,但我希望您了解我想要实现的目标

@Query("select distinct(p) from Parent p " + 
        (fetchChild ? " left join p.child c" : "") + 
        (fetchPets ? " left join p.pets pts" : "") +
        " where p.id=:id")
Foo getParentWithChildren(@Param("id") long id, @Param("fetchChild") boolean isFetchChild, @Param("fetchPets") boolean isFetchPets);

我有类似的可能吗?

1 个答案:

答案 0 :(得分:1)

您可以在界面中创建多个方法,并使用JPA 2.1中引入的EntityGraph功能,Spring Data JPA以各种方式支持这些功能:

http://docs.spring.io/spring-data/jpa/docs/1.11.0.RELEASE/reference/html/#jpa.entity-graph

public interface FooRepository extends JpaRepository<Foo, Long>{

    @EntityGraph(attributePaths = { "children" })
    @Query("select f from Foo f where f.id = :id")
    Foo getFooWithChildren(@Param("id") long id);

    @EntityGraph(attributePaths = { "pets" })
    @Query("select f from Foo f where f.id = :id")
    Foo getFooWithPets(@Param("id") long id);

    @EntityGraph(attributePaths = { "children", "pets" })
    @Query("select f from Foo f where f.id = :id")
    Foo getFooWithChildrenAndPets(@Param("id") long id);
}

这个问题是您需要为每个方法重复查询。能够将实体图作为参数传递给查询方法似乎是Spring Data JPA模块中缺少的有用功能。

我前一段时间在门票上提出但尚未更新:

https://jira.spring.io/browse/DATAJPA-645?filter=-2

此问题的答案中的链接Spring Data JPA And NamedEntityGraphs会建议在下方进行扩展,以便我们完成此操作:

https://github.com/Cosium/spring-data-jpa-entity-graph

使用此扩展程序,代码简化为:

public interface FooRepository extends JpaEntityGraphRepository<Foo, Long>{

}

并将其命名为:

Foo foo = fooRepository.findOne(1L, 
               new DynamicEntityGraph(Arrays.asList({"children");

Foo foo = fooRepository.findOne(1L, 
               new DynamicEntityGraph(Arrays.asList({"children", "pets"});