且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在Spring Data Rest项目中使用任意查询作为投影

更新时间:2023-09-02 22:46:16

问题非常广泛,涉及几个方面:

Question is quite broad and touches couple of aspects:

  • 使用 @Query
  • 的自定义JPA存储库方法
  • 在您的 @Query
  • 中选择结果
  • @Query 结果映射到接口
  • 通过 @RepositoryRestResource
  • 公开新的存储库方法
  • custom JPA repository method using @Query
  • selecting results in your @Query
  • mapping @Query results to an interface
  • exposing new repository method through @RepositoryRestResource

TLDR:写了一个有关几个基本测试的例子 https://github.com/ivarprudnikov/test-spring-jpa-repository-query-exposed-through-http

TLDR: wrote an example of what is talked about with couple of basic tests https://github.com/ivarprudnikov/test-spring-jpa-repository-query-exposed-through-http

正如您已经提到的那样,它非常简单,只需使用 @Query 注释一个方法,并确保您的返回类型与查询所返回的内容相对应,例如:

As you have mentioned it is quite straightforward, just annotate a method with @Query and make sure your return type corresponds to what is being returned from the query, eg:

public interface FooRepository extends JpaRepository<FooEntity, Long> {
    @Query(nativeQuery = true, value = "select f from foo f where f.name = :myParam")
    Optional<FooEntity> getInSomeAnotherWay(String myParam);
}

在您的 @Query

中选择结果

您已经给出了一个示例,但为了简化和简化,我将对其进行简化.

selecting results in your @Query

You have given an example already but I'll simplify to make it easier and shorter.

给出实体 FooEntity.java BarEntity.java :

@Entity
@Table(name = "foo")
public class FooEntity {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @OneToMany(mappedBy = "foo")
    private Set<BarEntity> bars = new HashSet<>();

    // getter setters excluded for brevity
}

@Entity
@Table(name = "bar")
public class BarEntity {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @ManyToOne(targetEntity = FooEntity.class)
    @JoinColumn(name = "foo_id", nullable = false, foreignKey = @ForeignKey(name = "fk_bar_foo"))
    private FooEntity foo;

    // getter setters excluded for brevity
}

我们现在要返回包含 FooEntity.name FooEntity.bars 的计数的自定义结果集:

We want now to return custom result set which contains FooEntity.name and count of FooEntity.bars:

SELECT f.name as name, count(b.id) as barCount FROM foo f, bar b WHERE f.id = :id AND b.foo_id = :id


+-----------------+----------+
| name            | barCount |
+-----------------+----------+
| Jonny tables    | 1        |
+-----------------+----------+

@Query 结果映射到接口

要映射以上结果集,我们需要一个接口,使吸气剂很好地反映出所选择的内容:

mapping @Query results to an interface

To map above result set we need an interface where getters nicely reflect what is being selected:

public interface ProjectedFooResult {
    String getName();
    Long getBarCount();
}

现在,我们可以将存储库方法重写为:

Now we can rewrite our repository method to:

@Query(nativeQuery = true, 
    value = "SELECT f.name as name, count(b.id) as barCount FROM foo f, bar b WHERE f.id = :id AND b.foo_id = :id")
Optional<ProjectedFooResult> getByIdToProjected(Long id);

通过 @RepositoryRestResource

公开新的存储库方法

对此我不是很熟悉,但是在添加了 org.springframework.data:spring-data-rest-hal-browser 依赖项之后,我得到了一个不错的接口,该接口在对存储库进行注释后公开了可用的方法. @RepositoryRestResource .对于包含上述详细信息的给定存储库:

exposing new repository method through @RepositoryRestResource

I am not very familiar with this but after adding org.springframework.data:spring-data-rest-hal-browser dependency I got this nice interface that exposed available methods after repository was annotated with @RepositoryRestResource. For a given repository which contains above mentioned details:

@RepositoryRestResource(path = "foo")
public interface FooRepository extends JpaRepository<FooEntity, Long> {
    @Query(nativeQuery = true, value = "SELECT f.name as name, count(b.id) as barCount FROM foo f, bar b WHERE f.id = :id AND b.foo_id = :id")
    Optional<ProjectedFooResult> getByIdToProjected(Long id);
}

在本地运行时,该方法将通过 http://localhost:8080/foo/search/getByIdToProjected?id = 1 公开.

the method will be exposed through http://localhost:8080/foo/search/getByIdToProjected?id=1 when running locally.

如上所述,参考实现在Github上https://github.com/ivarprudnikov/test-spring-jpa-repository-query-exposed-through-http

As mentioned above the reference implementation is on Github https://github.com/ivarprudnikov/test-spring-jpa-repository-query-exposed-through-http

其他帮助"Spring数据存储库的自定义实现"的文档