【问题标题】:Spring data dynamic @Query based on params possible?基于参数的Spring数据动态@Query可能吗?
【发布时间】:2017-06-18 14:42:45
【问题描述】:

我最近从 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);

我有类似的可能吗?

【问题讨论】:

  • 不,但是如果这是您的确切情况,您可以在接口中创建2个方法并根据isFetchChild调用适当的方法。
  • 实际上真正的父母拥有 5 个孩子,例如 5 个布尔参数。并且还有不同的组合。有时你想要孩子 1 和 3,有时只有 4 个,有时全部 5 个等等。那么我必须为所有可能的场景编写方法?

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


【解决方案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"});

【讨论】:

  • 谢谢!我会检查一下。问题,默认情况下内连接获取引用的实体吗?如果是这样,我可以指定我想要左连接或任何其他类型吗?
猜你喜欢
  • 2020-04-07
  • 1970-01-01
  • 2017-12-13
  • 2020-10-14
  • 1970-01-01
  • 2014-09-12
  • 2011-01-17
  • 1970-01-01
  • 2020-11-14
相关资源
最近更新 更多