programing

스프링 데이터 및 페이지 번호 지정 네이티브 쿼리

powerit 2023. 2. 22. 23:19
반응형

스프링 데이터 및 페이지 번호 지정 네이티브 쿼리

5 최신 데이터를 페이지 MySQL 5.6이 org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException를 클릭합니다.

업데이트: 20180306 이 문제는 Spring 2.0.4에서 해결되었습니다.아직도 이전 버전에 관심이 있거나 기존 버전에 얽매여 있는 사용자는 관련 답변과 코멘트를 확인하여 해결 방법을 확인하십시오.

예 50에 따르면 @Query from spring-data documentation에서는 다음과 같이 쿼리 자체와 countQuery를 지정할 수 있습니다.

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

NativeJpaQuery클래스에는 유효한 jpa 쿼리인지 확인하기 위한 다음 코드가 포함되어 있습니다.

public NativeJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, EvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
   super(method, em, queryString, evaluationContextProvider, parser);
   JpaParameters parameters = method.getParameters();
   boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
   boolean containsPageableOrSortInQueryExpression = queryString.contains("#pageable") || queryString.contains("#sort");
   if(hasPagingOrSortingParameter && !containsPageableOrSortInQueryExpression) {
       throw new InvalidJpaQueryMethodException("Cannot use native queries with dynamic sorting and/or pagination in method " + method);
   }
}

쿼리에 " " " 가 되어 있습니다.Pageable so '는 parameter 입니다.hasPagingOrSortingParametertrue ,, 이, 이, 찾고 있습니다#pageable ★★★★★★★★★★★★★★★★★」#sort「」의 queryString제공하지는 않습니다.

추가하려고 했습니다.#pageable쿼리의 마지막에 (댓글)이 표시되므로 검증이 통과되지만 실행 시 쿼리가 2가 아닌 3이라는 하나의 추가 파라미터를 예상한다는 점에서 실패합니다.

했을 경우, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」containsPageableOrSortInQueryExpression부에서false to 로.trueworks 쿼리가 잘 작동하면 행 실 다 리 니 이 지 는 습 에 왜 문 while 작,때 so 없 fine running the query it to my forqueryString그리고 어떻게 제공할지 모르겠어요.어떻게 제공해야 할지 모르겠어요.

어떤 도움이라도 주시면 감사하겠습니다.

업데이트 2018년 1월 30일 봄 데이터 프로젝트 개발자는 Jens Schauder의 PR과 함께 이 문제에 대한 수정 작업을 진행 중인 것으로 보입니다.

미리 사과드립니다만, 이것은 원래의 질문과 Janar로부터의 코멘트를 요약한 것입니다만…

같은 문제가 발생했습니다.Spring Data의 예 50을 페이지 부착 네이티브 쿼리를 필요로 하는 솔루션으로서 찾았습니다만, 기동시에 Spring은 네이티브 쿼리에 페이지 부착을 사용할 수 없다고 불평하고 있었습니다.

다음 코드를 사용하여 필요한 네이티브 쿼리를 성공적으로 실행했음을 보고하고 싶습니다.

    @Query(value="SELECT a.* "
            + "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
            + "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time)"
            + "ORDER BY a.id \n#pageable\n", 
        /*countQuery="SELECT count(a.*) "
            + "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
            + "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time) \n#pageable\n",*/
        nativeQuery=true)
public List<Author> findAuthorsUpdatedAndNew(Pageable pageable);

카운트 쿼리(코드 블록)은 카운트 쿼리(드 block블 록 웃 멘 음를있려 the하 count out)면용 is the사 in codequeryquery is코아 count) commented어되에 toPage<Author>쿼리의 반환 유형으로, 예상 매개 변수(#페이지) 댓글의 런타임 오류를 피하기 위해 "#페이지" 댓글에 대한 런타임 오류를 방지해야 합니다.쿼리의 반환 유형으로 예상되는 파라미터의 수(회피책의 회피책)에 대한 런타임 오류를 피하기 위해 "# pageable" 코멘트 주변의 새 행이 필요합니다.~하다

버전 2.0.4 이전 Spring Data JPA를 사용한 프로그램 해킹입니다.

코드는 Postgre와 함께 동작했습니다.SQL 및 MySQL:

public interface UserRepository extends JpaRepository<User, Long> {

@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY ?#{#pageable}",
       countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
       nativeQuery = true)
   Page<User> findByLastname(String lastname, Pageable pageable);   
}

ORDER BY ?#{#pageable}을 위한Pageable.countQuery을 위한Page<User>.

H2를 테스트 데이터베이스로 사용하고 런타임에 MySQL을 사용하는 레코드에 대해서만 이 방법이 작동합니다(예: 그룹의 최신 개체).

@Query(value = "SELECT t.* FROM t LEFT JOIN t AS t_newer " +
        "ON t.object_id = t_newer.object_id AND t.id < t_newer.id AND o_newer.user_id IN (:user_ids) " +
        "WHERE t_newer.id IS NULL AND t.user_id IN (:user_ids) " +
        "ORDER BY t.id DESC \n-- #pageable\n",
        countQuery = "SELECT COUNT(1) FROM t WHERE t.user_id IN (:user_ids) GROUP BY t.object_id, t.user_id",
        nativeQuery = true)
Page<T> findByUserIdInGroupByObjectId(@Param("user_ids") Set<Integer> userIds, Pageable pageable);

Spring Data JPA 1.10.5, H2 1.4.194, MySQL Community Server 5.7.11-log(innodb_version 5.7.11).

Spring Boot의 최신 버전을 사용하는 사용자를 위한 플레이스 홀더로서 이 답변을 추가합니다.Spring Boot 2.4.3에서는 회피책 중 어느 것도 필요하지 않다는 것을 알게 되었습니다.다음 코드는 개봉 즉시 사용할 수 있었습니다.

public interface UserRepository extends JpaRepository<User, Long> {
    @Query(value="SELECT * FROM USERS WHERE LASTNAME = ?1", nativeQuery=true)
    Page<User> findByLastname(String lastname, Pageable pageable);
}

countQuery정의가 필요없고, 에 대한 호출이 있었다.Page#getTotalElements()실제로 JPA의 내부 카운트 쿼리에 의해 반환된 올바른 카운트를 이미 반환하고 있었습니다.

위의 코드는 매우 강력하며 네이티브 쿼리를 통해 페이지 매김을 제공하지만 실제 Java 엔티티로 반환됩니다(추악하고 부피가 큰 것이 아니라).List<Object[]>(필요한 경우가 있습니다.

이것을 시험해 보세요.

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY /*#pageable*/",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

("/* */"위해서Oracle notation)

@Lasneyx와 같은 증상이 있습니다.Postgres 네이티브 쿼리 회피책

@Query(value = "select * from users where user_type in (:userTypes) and user_context='abc'--#pageable\n", nativeQuery = true)
List<User> getUsersByTypes(@Param("userTypes") List<String> userTypes, Pageable pageable);

오라클 데이터베이스를 사용했는데 결과는 나오지 않았지만 위에서 d-man이 말한 쉼표 생성 오류가 발생했습니다.

그 후, 저의 솔루션은 다음과 같습니다.

Pageable pageable = new PageRequest(current, rowCount);

Pagable을 작성할 때 순서 없이 확인할 수 있습니다.

DAO의 방법은 다음과 같습니다.

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 /*#pageable*/ ORDER BY LASTNAME",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
 }

페이지네이션은 에 성공적으로 통합할 수 있었습니다.

스프링 데이터 jpa-2.1.6

다음과 같이 합니다.

@Query(
 value = “SELECT * FROM Users”, 
 countQuery = “SELECT count(*) FROM Users”, 
 nativeQuery = true)
Page<User> findAllUsersWithPagination(Pageable pageable);

다음 두 가지 접근 방식 모두 MySQL에서 네이티브 쿼리에 페이지를 매길 때 잘 작동합니다.H2에서는 동작하지 않습니다.sql 구문 오류가 발생합니다.

  • ##{#페이지 가능}주문
  • a.id으로 주문 \n#페이지 가능\n

MS SQL SERVER에서는 "ORDER BY ID \n#pageable\n" 대신 "ORDER BY ID DESC\n--#pageable\n"을 사용하여 사용할 수 있었습니다.

Groovy에서는 (Postgres를 사용하고 있습니다) 이것이 효과가 있었습니다.

@RestResource(path="namespaceAndNameAndRawStateContainsMostRecentVersion", rel="namespaceAndNameAndRawStateContainsMostRecentVersion")
    @Query(nativeQuery=true,
            countQuery="""
            SELECT COUNT(1) 
            FROM 
            (
                SELECT
                ROW_NUMBER() OVER (
                    PARTITION BY name, provider_id, state
                    ORDER BY version DESC) version_partition,
                *
                FROM mydb.mytable
                WHERE
                (name ILIKE ('%' || :name || '%') OR (:name = '')) AND
                (namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND
                (state = :state OR (:state = ''))
            ) t
            WHERE version_partition = 1
            """,
            value="""
            SELECT id, version, state, name, internal_name, namespace, provider_id, config, create_date, update_date 
            FROM 
            (
                SELECT 
                ROW_NUMBER() OVER (
                    PARTITION BY name, provider_id, state
                    ORDER BY version DESC) version_partition,
                *
                FROM mydb.mytable
                WHERE 
                (name ILIKE ('%' || :name || '%') OR (:name = '')) AND
                (namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND
                (state = :state OR (:state = ''))       
            ) t            
            WHERE version_partition = 1             
            /*#{#pageable}*/
            """)
    public Page<Entity> findByNamespaceContainsAndNameContainsAndRawStateContainsMostRecentVersion(@Param("namespace")String namespace, @Param("name")String name, @Param("state")String state, Pageable pageable)

여기서 중요한 것은 다음과 같습니다./*#{#pageable}*/

정렬과 페이지 매김을 할 수 있습니다.http://localhost:8080/api/v1/entities/search/namespaceAndNameAndRawStateContainsMostRecentVersion?namespace=&name=&state=http=0&size=3&sort=name, desc.

이 문제에 주의해 주세요.스프링 페이지 가능은 @Column 이름을 변환하지 않습니다.

  • 사용자 지정 저장소 만들기:
public interface ProductsCustomRepository extends JpaRepository<ProductResultEntity, Long> {
    @Query(
        value = "select tableA.id, tableB.bank_name from tableA join tableB on tableA.id = tableB.a_id where tableA.id = :id
        and (:fieldX is null or tableA.fieldX LIKE :fieldX)",
        countQuery = "select count(*) from tableA join tableB on tableA.id = tableB.a_id where tableA.id = :id
        and (:fieldX is null or tableA.fieldX LIKE :fieldX)",
        nativeQuery = true
    )
    Page<ProductResultEntity> search(@Param("id") Long aId,
        @Param("fieldX") String keyword, Pageable pageable
    );
}
  • 조회로 보기 만들기:
create view zzz as select * from tableA join tableB on tableA.id = tableB.a_id
  • 해당 zz 뷰에서 Product ResultEntity 생성(완료 시 뷰 zz 삭제)
  • 통화 기능을 테스트하고 즐기십시오.
productsRepository.search("123", "%BANK%", PageRequest.of(0, 5, Sort.by(Sort.Direction.ASC, "id")));
  • 엔티티:
@Entity
public class ProductResultEntity {
    private Long id;
    private String bank;

    @Id
    @Column(name = "id", nullable = false)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Column(name = "bank_name", nullable = false)
    public String getBank() {
        return bank;
    }

    public void setBank(String bank) {
        this.bank = bank;
    }
}

다음과 같이 동작합니다.

public interface UserRepository extends JpaRepository<User, Long> {
    @Query(value = "select * from (select (@rowid\\:=@rowid+1) as RN, u.* from USERS u, (SELECT @rowid\\:=0) as init where  LASTNAME = ?1) as total"+
        "where RN between ?#{#pageable.offset-1} and ?#{#pageable.offset + #pageable.pageSize}",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
    Page<User> findByLastname(String lastname, Pageable pageable);
}

아래는 MS SQL에서 작업한 경우입니다.

 @Query(value="SELECT * FROM ABC r where r.type in :type  ORDER BY RAND() \n-- #pageable\n ",nativeQuery = true)
List<ABC> findByBinUseFAndRgtnType(@Param("type") List<Byte>type,Pageable pageable);

아래 코드를 사용하고 있습니다.일해

@Query(value = "select * from user usr" +
  "left join apl apl on usr.user_id = apl.id" +
  "left join lang on lang.role_id = usr.role_id" +
  "where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds ORDER BY ?#{#pageable}",
  countQuery = "select count(*) from user usr" +
      "left join apl apl on usr.user_id = apl.id" +
      "left join lang on lang.role_id = usr.role_id" +
      "where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds",
  nativeQuery = true)
Page<AplUserEntity> searchUser(@Param("scrname") String scrname,@Param("uname") String  uname,@Param("roleIds") List<Long> roleIds,Pageable pageable);

쿼리 및 카운트 쿼리에서 \n#pageable\n을 삭제한 것이 도움이 되었습니다.스프링 부트 버전: 2.1.5.릴리즈 DB : Mysql

h2 및 MySQL에 대해 아래 코드를 사용할 수 있습니다.

    @Query(value = "SELECT req.CREATED_AT createdAt, req.CREATED_BY createdBy,req.APP_ID appId,req.NOTE_ID noteId,req.MODEL model FROM SUMBITED_REQUESTS  req inner join NOTE note where req.NOTE_ID=note.ID and note.CREATED_BY= :userId "
        ,
         countQuery = "SELECT count(*) FROM SUMBITED_REQUESTS req inner join NOTE note WHERE req.NOTE_ID=note.ID and note.CREATED_BY=:userId",
        nativeQuery = true)
Page<UserRequestsDataMapper> getAllRequestForCreator(@Param("userId") String userId,Pageable pageable);

다음 코드를 사용하여 달성할 수 있습니다.

@Query(value = "SELECT * FROM users u WHERE  ORDER BY ?#{#pageable}", nativeQuery = true)
List<User> getUsers(String name, Pageable pageable);

ORDER BY ?#{#pageable}사용하여 페이지 요청을 귀하의 메서드로 전달하기만 하면 됩니다.

맛있게 드세요!

@Query(value = "select " +
//"row_number() over (order by ba.order_num asc) as id, " +
"row_number() over () as id, " +
"count(ba.order_num),sum(ba.order_qty) as sumqty, " +
"ba.order_num, " +
"md.dpp_code,md.dpp_name, " +
"from biz_arrangement ba " +
"left join mst_dpp md on ba.dpp_code = md.dpp_code " +
"where 1 = 1 " +
"AND (:#{#flilter.customerCodeListCheck}='' OR ba.customer_code IN (:#{#flilter.customerCodeList})) " +
"AND (:#{#flilter.customerNameListCheck}='' OR ba.customer_name IN (:#{#flilter.customerNameList})) " +
"group by " +
"ba.order_num, " +
"md.dpp_code,md.dpp_name ",
countQuery = "select " +
"count ( " +
"distinct ( " +
"ba.order_num, " +
"md.dpp_code,md.dpp_name) " +
")" +
"from biz_arrangement ba " +
"left join mst_dpp md on ba.dpp_code = md.dpp_code " +
"where 1 = 1 " +
"AND (:#{#flilter.customerCodeListCheck}='' OR ba.customer_code IN (:#{#flilter.customerCodeList})) " +
"AND (:#{#flilter.customerNameListCheck}='' OR ba.customer_name IN (:#{#flilter.customerNameList})) ",
nativeQuery = true)
Page<Map<String, Object>> nativeQueryDynamicPageAndSort(@Param("flilter") Flilter flilter, Pageable pageable);

추가할 필요가 없습니까?#{#페이지 가능}, 문제가 생긴 것은 사용했을 때 입니다.

row_number() over (order by ba.order_num asc) as id,

로 변경하면 입력 정렬이 작동하지 않습니다.

row_number() over () as id,

동적 입력 정렬과 페이지 번호부여 모두 OK!

이것은 행 ID를 가진 쿼리별 그룹입니다.

/#pageable/을(를) 로 대체하시겠습니까?# { # pageable } toination 페이지 번호 부여를 허용합니다.PageableDefault를 추가하면 페이지 요소의 크기를 설정할 수 있습니다.

언급URL : https://stackoverflow.com/questions/38349930/spring-data-and-native-query-with-pagination

반응형