In einem Webprojekt, das die neuesten Spring-Daten (1.10.2) mit einer MySQL 5.6-Datenbank verwendet, versuche ich, eine native Abfrage mit Paginierung zu verwenden, aber org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException
beim Start tritt eine auf.
UPDATE : 20180306 Dieses Problem wurde jetzt in Spring 2.0.4 behoben. Für diejenigen, die noch interessiert sind oder mit älteren Versionen nicht weiterkommen, überprüfen Sie die entsprechenden Antworten und Kommentare auf Problemumgehungen.
Gemäß Beispiel 50 unter Verwenden von @Query aus der Spring-Data-Dokumentation ist dies möglich, indem die Abfrage selbst und eine countQuery wie folgt angegeben werden:
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);
}
Aus Neugier kann NativeJpaQuery
ich in der Klasse sehen, dass es den folgenden Code enthält, um zu überprüfen, ob es sich um eine gültige jpa-Abfrage handelt:
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);
}
}
Meine Abfrage enthält einen Pageable
Parameter, so hasPagingOrSortingParameter
ist true
, aber es ist auch für eine Suche #pageable
oder #sort
Sequenz innerhalb der queryString
, die ich nicht bieten.
Ich habe versucht, #pageable
am Ende meiner Abfrage etwas hinzuzufügen (es ist ein Kommentar), wodurch die Validierung bestanden wird. Bei der Ausführung schlägt jedoch fehl, dass die Abfrage einen zusätzlichen Parameter erwartet: 3 anstelle von 2.
Das Komische ist, dass die Abfrage , wenn ich während der Ausführung manuell containsPageableOrSortInQueryExpression
von false
zu wechsle true
, einwandfrei funktioniert, sodass ich nicht weiß, warum diese Zeichenfolge bei mir überprüft wird queryString
und ich nicht weiß, wie ich sie bereitstellen soll.
Jede Hilfe wäre sehr dankbar.
Update 30.01.2008 Es scheint, dass Entwickler des Spring-Data-Projekts mit einer PR von Jens Schauder an einer Lösung für dieses Problem arbeiten
quelle
Antworten:
Ich entschuldige mich im Voraus, dies fasst die ursprüngliche Frage und den Kommentar von Janar ziemlich gut zusammen , aber ...
Ich habe das gleiche Problem: Ich fand das Beispiel 50 von Spring Data als Lösung für meine Notwendigkeit, eine native Abfrage mit Paginierung zu haben, aber Spring beschwerte sich beim Start, dass ich die Paginierung nicht mit nativen Abfragen verwenden konnte.
Ich wollte nur berichten, dass es mir gelungen ist, die benötigte native Abfrage mithilfe der Paginierung mit dem folgenden Code erfolgreich auszuführen:
@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);
Die countQuery (die im Codeblock auskommentiert ist) wird
Page<Author>
als Rückgabetyp der Abfrage verwendet. Die Zeilenumbrüche um den Kommentar "#pageable" werden benötigt, um den Laufzeitfehler bei der Anzahl der erwarteten Parameter zu vermeiden (Problemumgehung des Problemumgehung). Ich hoffe, dieser Fehler wird bald behoben ...quelle
?#{#pageable}
funktioniert stattdessen\n#pageable\n
.:authorId
. Ich änderte Ihr\n#pageable\n
zu--#pageable\n
für postgresql. Die countQuery wird wie von Ihnen vorgeschlagen benötigt, da in vielen Beispielen List <> anstelle von Page <> verwendet wird. Ihre Antwort war genau richtig. Ich habe die gleichen Dokumente durchgesehen und ohne Ihre Antwort hätte ich einfach aufgegeben./*:pageable*/
funktioniert nur (mit SQL Server, Hibernate 5.4.1.Final und Spring Boot 2.2.1)Dies ist ein Hack für Programme, die Spring Data JPA vor Version 2.0.4 verwenden .
Code hat mit PostgreSQL und MySQL funktioniert:
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}
ist fürPageable
.countQuery
ist fürPage<User>
.quelle
spring.jpa.show-sql=false
einapplication.properties
; 2.?#{#pageable}
Legen Sie in Ihrer nativeQuery fest und 3. analysieren Sie das Ergebnis-SQL aus dem Protokoll. @Lasneyx hat die Ausgabe DATAJPA-928 für diese Besonderheit von Spring Data JPA erstellt.Nur für den Datensatz, bei dem H2 als Testdatenbank und MySQL zur Laufzeit verwendet werden, funktioniert dieser Ansatz (Beispiel ist das neueste Objekt in der Gruppe ):
@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-Protokoll (innodb_version 5.7.11).
quelle
Ich habe genau das gleiche Symptom wie @Lasneyx. Meine Problemumgehung für die native Postgres-Abfrage
@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);
quelle
Versuche dies:
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); }
(
"/* */"
fürOracle notation
)quelle
Ich benutze die Oracle-Datenbank und habe nicht das Ergebnis erhalten, sondern einen Fehler mit dem generierten Komma, über den D-Man oben gesprochen hat.
Dann war meine Lösung:
Pageable pageable = new PageRequest(current, rowCount);
Wie Sie ohne Reihenfolge beim Erstellen von Pagable sehen können.
Und die Methode im 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); }
quelle
Beide folgenden Ansätze funktionieren gut mit MySQL zum Paginieren nativer Abfragen. Sie funktionieren jedoch nicht mit H2. Es wird den SQL-Syntaxfehler beschweren.
quelle
Die Verwendung von "ORDER BY id DESC \ n-- #pageable \ n" anstelle von "ORDER BY id \ n # pageable \ n" funktionierte bei mir mit MS SQL SERVER
quelle
Ich konnte Pagination erfolgreich integrieren
wie folgt.
@Query( value = “SELECT * FROM Users”, countQuery = “SELECT count(*) FROM Users”, nativeQuery = true) Page<User> findAllUsersWithPagination(Pageable pageable);
quelle
Es funktioniert wie folgt:
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); }
quelle
Für mich arbeitete unten in 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);
quelle
Ich verwende den folgenden Code. Arbeiten
@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);
quelle
Das Entfernen von \ n # pageable \ n sowohl aus der Abfrage als auch aus der Zählabfrage hat bei mir funktioniert. Springboot-Version: 2.1.5.RELEASE DB: MySQL
quelle
Das hat bei mir (ich benutze Postgres) in Groovy funktioniert:
@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)
Der Schlüssel hier war zu verwenden:
/*#{#pageable}*/
Es ermöglicht mir das Sortieren und Paginieren. Sie können es testen, indem Sie Folgendes verwenden: http: // localhost: 8080 / api / v1 / entity / search / namespaceAndNameAndRawStateContainsMostRecentVersion? Namespace = & name = & state = shared & page = 0 & size = 3 & sort = name, desc
Achten Sie auf dieses Problem: Spring Pageable übersetzt den @ Column-Namen nicht
quelle
Sie können den folgenden Code für h2 und MySQl verwenden
@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);
quelle
Durch Ersetzen von / #pageable / durch? # {# Pageable} kann die Paginierung durchgeführt werden. Durch Hinzufügen von PageableDefault können Sie die Größe der Seitenelemente festlegen.
quelle