어떤 저장소에 임의의 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을 "검색"을 사용하여 호출 할 수 있습니다. 내 방법을 참조 getByIdProjectedForScreen42
URL에 // localhost를 : 9091 / API / A / 검색 HTTP 목록을. 나는 (내가 그이 "오른쪽"방법이라고 생각)처럼 사용하고 싶습니다 // localhost를 : 8080 / API / 투사 = ACustomPage42DTOProjection을 HTTP .
질문은 매우 광범위하고 측면의 몇 접촉 :
- 사용자 정의 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.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
:
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