99 votes

Quelle est l'alternative de la clause LIMIT dans JPQL ?

Je travaille avec des requêtes PostgreSQL implémentées dans JPQL.

Voici un exemple de requête psql native qui fonctionne bien,

SELECT * FROM students ORDER BY id DESC LIMIT 1;

La même requête en JPQL ne fonctionne pas,

@Query("SELECT s FROM Students s ORDER BY s.id DESC LIMIT 1")

Students getLastStudentDetails();

Il semble que la clause LIMIT ne fonctionne pas dans JPQL.

Selon la documentation JPA, nous pouvons utiliser setMaxResults/setFirstResult Quelqu'un peut-il me dire comment je peux l'utiliser dans ma requête ci-dessus ?

0 votes

@NeilStockton ok, j'étais un peu confus à ce sujet, maintenant comment utiliser setMaxResults/setFirstResult dans ma requête jpql ci-dessus ?

2 votes

J'ai utilisé ceci qui a également fonctionné pour moi @Query(value = "SELECT * FROM students ORDER BY id DESC LIMIT 1", nativeQuery = true) Object getLastStudentDetails();

1 votes

Non. Vous n'êtes pas obligé d'utiliser une requête native. Lisez les questions-réponses liées ! !!

114voto

M. Deinum Points 34051

Vous utilisez JPQL qui ne permet pas de limiter les résultats de cette manière. Lorsque vous utilisez JPQL natif, vous devez utiliser setMaxResults pour limiter les résultats.

Cependant, vous utilisez Spring Data JPA, ce qui rend la tâche assez facile. Voir ici dans le guide de référence sur la façon de limiter les résultats en fonction d'une requête. Dans votre cas, la méthode find suivante ferait exactement ce que vous voulez.

findFirstByOrderById();

Vous pouvez également utiliser un Pageable avec votre requête au lieu d'un LIMIT clause.

@Query("SELECT s FROM Students s ORDER BY s.id DESC")
List<Students> getLastStudentDetails(Pageable pageable);

Ensuite, dans votre code d'appel, faites quelque chose comme ceci (comme expliqué) ici dans le guide de référence).

getLastStudentDetails(new PageRequest(0,1));

Les deux devraient donner le même résultat, sans qu'il soit nécessaire d'avoir recours à du SQL pur.

1 votes

New PageRequest(0,1) a fonctionné pour moi au lieu de new PageableRequest. J'utilise Spring 1.5.6. Est-ce que quelque chose a changé dans JPA 2.1 ?

3 votes

Votre code ne fonctionne pas car 1) LIMIT 1 sur @Query et 2) getLastStudentDetails a un paramètre de type Pageable mais renvoie un seul objet. Cela échouera au démarrage de l'application ( IllegalStateException: Method has to have one of the following return types! [interface org.springframework.data.domain.Slice, interface java.util.List, interface org.springframework.data.domain.Page] )

10 votes

new PageRequest a été déprécié. Utilisez maintenant PageRequest.of(page, size)

22voto

dwnz Points 516

Comme indiqué dans les commentaires, JPQL ne supporte pas le LIMIT mot-clé.

Vous pouvez y parvenir en utilisant l'option setMaxResults mais si ce que vous voulez n'est qu'un seul élément, alors utilisez la fonction getSingleResult - il lève une exception si aucun élément n'est trouvé.

Donc, votre requête serait quelque chose comme :

TypedQuery<Student> query = entityManager.createQuery("SELECT s FROM Students s ORDER BY s.id DESC", Student.class);    
query.setMaxResults(1);

Si vous voulez définir un décalage de départ spécifique, utilisez query.setFirstResult(initPosition) ; aussi

3 votes

Salut, j'ai utilisé ceci qui a également fonctionné pour moi @Query(value = "SELECT * FROM students ORDER BY id DESC LIMIT 1", nativeQuery = true) Object getLastStudentDetails();

2 votes

Il n'y a aucun intérêt à utiliser Hibernate si vous devez utiliser une requête native.

0 votes

@SiddharthSachdeva oui, c'est vrai.

14voto

Manish Joshi Points 1

Bonjour, pour récupérer une seule ligne et utiliser LIMIT dans jpql, nous pouvons dire à jpql si c'est une requête native.

( using - nativeQuery=true )

Voici l'utilisation

@Query("SELECT s FROM Students s ORDER BY s.id DESC LIMIT 1", nativeQuery=true)
Students getLastStudentDetails();

2 votes

C'est une déclaration SQL native maintenant, pas JPQL.

7voto

David Jesus Points 1031

Vous ne pouvez pas utiliser Limit sur HQL parce que Limit dépend du fournisseur de la base de données, donc Hibernate ne le laisse pas passer HQL requête.

Une façon de procéder est d'utiliser une sous-requête :

@Query("FROM Students st WHERE st.id = (SELECT max(s.id) FROM Students s)")
Students getLastStudentDetails();

4voto

greenhorn Points 309

JPQL ne permet pas d'ajouter le limite à la requête générée par le HQL. Vous obtiendrez l'exception suivante.

org.hibernate.hql.internal.ast.QuerySyntaxException : jeton inattendu : LIMIT près de la ligne 1

Mais ne vous inquiétez pas, il existe une alternative pour utiliser le mot-clé limite dans la requête générée par le HQL en utilisant les étapes suivantes.

Sort.by(sortBy).descending() // Récupère les enregistrements par ordre décroissant.

pageSize = 1 // Récupérer le premier enregistrement de l'ensemble des résultats par ordre décroissant.

Référez-vous à la classe de service suivante

Service :

@Autowired
StudentRepository repository; 

public List<Student> getLastStudentDetails(Integer pageNo, Integer pageSize, String sortBy)
{
    Integer pageNo = 0;
    Integer pageSize = 1;
    String sortBy = "id";
    Pageable paging = PageRequest.of(pageNo, pageSize, Sort.by(sortBy).descending());

    Slice<Student> pagedResult = repository.findLastStudent(paging);

    return pagedResult.getContent();
}

L'interface de votre dépôt doit implémenter la fonction PagingAndSortingRepository

Dépôt :

public interface StudentRepository extends JpaRepository<Student,Long>, PagingAndSortingRepository<Student,Long>{

    @Query("select student from Student student")
    Slice<Student> findLastStudent(Pageable paging);
}

Cela ajoutera le mot-clé limite à votre requête, que vous pourrez voir dans la console. J'espère que cela vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X