봄의 데이터 나머지 프로젝트에 투사와 같은 임의의 쿼리를 사용하여

Lubo :

어떤 저장소에 임의의 SQL 쿼리 (I 평균 네이티브 SQL 쿼리)를 사용할 수 있습니까? 내 실제 문제는 이것이다 :

@Data //lombok thing
@Entity
public class A extends AuditModel {
  private long id;
  private String name;

  @OneToMany(mappedBy="a") //Comments.a is owning side of association, i.e. comments table does have column called a_id as foreign key
  @ToString.Exclude
  private Set<Comments> comments = new HashSet();

  @OneToMany(mappedBy="a") //SimpleFile.a is owning side of association
  private Set<SimpleFile> comments = new HashSet();
}

나는 HAL + JSON 표현을 사용하여 좋은 침전물 인터페이스를 공개 저장소 (repository)를 가지고보다. 나는 하나의 요청에 한 페이지의 데이터를로드하는 데 특히 인해 웹 UI에 몇 가지 투사 / 전망을 풍부하게하는 것을 시도하고있다. 나는 excerps과의 돌기 알고 있지만 충분히 강력하지 않을 것 같다.

@Repository
@RepositoryRestResource
@Transactional(readOnly = true)
public interface ARepository extends PagingAndSortingRepository<A, Long> {
  Page<A> findByNameContaining(String namePart, Pageable pageable);
  @Query(
    value = "SELECT a.name,\n" +
      "(SELECT CAST(count(ac.id) AS int) FROM COMMENTS ac WHERE ac.a_id = a.id),\n" +
      "(SELECT listagg(asf.id) FROM SIMPLE_FILES asf WHERE asf.a_id = a.id)\n" +
      "FROM AS a\n" +
      "WHERE a.id = :id",
    nativeQuery = true
  )
  Optional<ACustomPage42DTO> getByIdProjectedForScreen42(Long id);
}

(나는 JPQL에 익숙하지 않은 나처럼) 나는 또한 JPQL를 사용하는 것을 시도했다, 그러나 나는 가입을 불러오는 데에 문제가 있었다. 내 마지막 평가 쿼리는 다음과 같이했다 :

@Query("SELECT new sk.qpp.qqq.documents.projections.ACustomPage42DTO(" +
  "a " +
  "(SELECT CAST(count(ac) AS int) FROM COMMENTS ac WHERE ac.a = a)" +
  ")\n" +
  "FROM A a\n" +
  "LEFT JOIN FETCH a.simpleFiles\n" +
  "WHERE a.id = :id"
)

나는 (필요할 때 이상적으로 행동에 일부 특정 링크가) 정의 및 복잡한 쿼리가 DTO에 반환 할 구현하기 위해 무엇이 최선인지 방법에 대한 몇 가지 일반적인 조언을 좀하고 싶습니다.

PS : 인터페이스를 구현하는 간단한 (프리미티브) 데이터 일을 반환. 또한 (단순 종류 및 유형의 단일 인스턴스와 사용자 정의 DAO 인스턴스의 작품을 만들 수 JPQL를 사용하여 A예를 들면). 주어진 엔티티 엔드 포인트의 검색 방법에 나타나지 않습니다 주어진 쿼리 방법을 사용하는 방법. 내가하고 싶은, 그래서 뭔가 더 합리적인하고 싶은 봄의 데이터 나머지에 정의 된 프로젝션 프로젝트.

내 통제하에 완전히 내 DTO 객체가 있습니다. 나는 그것을 사용하는 것을 선호 @Value또는 @Data프로젝트 롬복에서 주석,하지만 필요하지 않습니다. 또한 (간단한 데이터 및 간단한 데이터에 대한 유사 클래스 작품에 대한 인터페이스가 작동을 사용) DTO 정의의 다음 버전을 시도했다.

interface ACustomPage42DTO {
    String getName();
    long getCommentsCount();
    Object getAsdf();
}

또는 () 메소드 수, 또는 계산 된 데이터에 대한 일부 사용자 지정 게터 사용자 정의 toString처럼, 약간의 보너스와 함께 해당 클래스를 사용하여 :

@Value //lombok thing, imutable "POJO"
public class ACustomPage42DTO {
    String name;
    long commentsCount;
    Set<SimpleFile> simpleFiles;
    public ACustomPage42DTO(A a, long count) {
        // constructor used by JPQL, if it works
        name = a.getName();
        this.commentsCount = count;
        this.simpleFiles = a.getSimpleFiles(); // should be already fetched, due to fetch join in JPQL
    }
}

두 작업 접근법 대신에 투사의, URL을 "검색"을 사용하여 호출 할 수 있습니다. 내 방법을 참조 getByIdProjectedForScreen42URL에 // localhost를 : 9091 / API / A / 검색 HTTP 목록을. 나는 (내가 그이 "오른쪽"방법이라고 생각)처럼 사용하고 싶습니다 // localhost를 : 8080 / API / 투사 = ACustomPage42DTOProjection을 HTTP .

Aivaras :

질문은 매우 광범위하고 측면의 몇 접촉 :

  • 사용자 정의 JPA 저장소 방법을 사용하여 @Query
  • 의 선택 결과 당신의 @Query
  • 매핑 @Query인터페이스에 결과를
  • 저장소를 통해 새로운 노광 법 @RepositoryRestResource

TLDR가 : 기본 테스트의 부부와 함께 이야기 무엇의 예를 쓴 https://github.com/ivarprudnikov/test-spring-jpa-repository-query-exposed-through-http

사용자 정의 JPA 저장소 방법을 사용하여 @Query

당신이 매우 간단 언급 한 것처럼, 단지와 방법을 주석 @Query하고 쿼리, 예로부터 반환되는 것과 반드시 수익 형 대응합니다

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

이미 예를 준하지만 난 그게 더 쉽고 짧게하기 위해 단순화 수 있습니다.

을 감안할 때 기관 FooEntity.javaBarEntity.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:

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인터페이스에 결과를

그 결과 위의 매핑하려면 게터가 잘 선택되고있는 것을 반영하는 곳에 우리가 인터페이스를 필요로 설정 :

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

이제 우리는 우리의 저장소 방법을 다시 작성할 수 있습니다 :

@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. 언급 한 사항 위에 포함 주어진 저장소의 경우 :

@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로컬로 실행되는 경우.

참조 구현 Github에서 전술 한 바와 같이에 https://github.com/ivarprudnikov/test-spring-jpa-repository-query-exposed-through-http

'봄의 데이터 저장소에 대한 사용자 정의 구현'에 대한 추가 도움이 문서

추천

출처http://43.154.161.224:23101/article/api/json?id=280291&siteId=1