18

一个快速的问题,因为我确信这很愚蠢。我有以下可以在 NetBeans sql 命令窗口中执行的查询:

SELECT TOP 25 * FROM ARCUST_BIG  WHERE arcustno<='300000' ORDER BY arcustno DESC

我的目标是将它放在我的 ArcustRepository 类中:

公共接口 ArcustRepository 扩展 JpaRepository {

Arcust findByPrimaryKey(String id);

@Query("SELECT COUNT(a) FROM Arcust a")
Long countAll();

@Query("SELECT TOP 25 a FROM Arcust a WHERE a.arcustno<='?1' ORDER BY a.arcustno DESC")
List<Arcust> findByTop(String arcustno);
}

但是,该 findBytop 查询似乎不起作用,当我使用 tomcat7 启动我的服务时返回:

2013-08-15 08:15:20 ERROR ContextLoader:319 - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'arcustService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.waudware.pics.repository.ArcustRepository com.waudware.pics.service.ArcustService.arcustRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'arcustRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.waudware.pics.repository.ArcustRepository.findByTop(java.lang.String)!
Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.waudware.pics.repository.ArcustRepository.findByTop(java.lang.String)!
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: 25 near line 1, column 12 [SELECT TOP 25 a FROM com.waudware.pics.domain.Arcust a WHERE a.arcustno<='?1' ORDER BY a.arcustno DESC]
4

7 回答 7

22

# 纯 SQL

使用“限制”

SELECT * FROM ARCUST_BIG 
WHERE arcustno<='300000' ORDER BY arcustno DESC Limit 0, 25

注意:JPA 支持使用方法createNativeQuery()或使用注释@NamedNativeQuery JPA Native Query 选择和转换对象 对象来创建本机查询


# JPA

List<Arcust> findTop25ByArcustnoLessThanOrderByArcustnoDesc(String arcustno);
于 2013-08-15T12:32:39.920 回答
19

我会说你需要

List<Arcust> findTop25ByArcustnoLessThanOrderByArcustnoDesc(String arcustno);

这将使用 JPA 并且可能适用于所有数据库,将从 SPRING JPA 1.7.0 (Evans release train) 开始工作

我实现 CrudRepository 而不是 JpaRepository

于 2016-10-06T20:44:19.713 回答
11

我不确定 Rakesh 的回答是否正确。他似乎在写 SQL,而不是 JPA 查询语法。
我尝试在 JPA @Query 中使用 LIMIT 并得到一个异常说“限制”无法识别。

@Query("select d from Device d where d.deviceName like CONCAT('%', :deviceName, '%') and d.deviceId not in :notList ORDER BY deviceName DESC Limit 1001")

Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: Limit near line 1, column 162

另外,请参阅 Hari Shankar 的这个答案,其中说 JPA 不支持“限制”: JPA 不支持“限制”

于 2015-02-13T21:58:27.460 回答
7

您可以在存储库中使用您的查询,无需 TOP 25:

@Query("SELECT a FROM Arcust a WHERE a.arcustno<='?1' ORDER BY a.arcustno DESC")
    List<Arcust> findByTop(String arcustno, Pageable pageable);
}

在 Service 中,使用一个 PageRequest,返回一个 Page 对象:

Page<Arcust> arcusts = arcustRepository.findByTop(arcustno, PageRequest.of(0, 25));
List<Arcust> arcust = arcusts.getContent();
于 2019-09-05T10:26:37.250 回答
4

实际上,JPQL 中不知道“限制”,并且在某些数据库方言中也不知道(例如,MySQL 知道,Oracle 不知道)它只能用于本机查询并且依赖于数据库。

在 spring-data 中,您还可以使用本机查询:对于 MySQl 可能有效:
@Query(value="SELECT * FROM ARCUST_BIG WHERE arcustno<='300000' ORDER BY arcustno DESC Limit 0, 25", nativeQuery=true)

但是,对于 Oracle-DB,您必须使用以下内容:
@Query(value="SELECT * FROM ARCUST_BIG WHERE rownum<=25 and arcustno<='300000' ORDER BY arcustno DESC", nativeQuery=true)

据我所知,spring-data(从 1.7 版开始)承诺 Top/First 也可以与 @Query 一起使用——但我也无法让它工作,因此上述“解决方法”可能会有所帮助。

于 2015-03-31T15:58:03.767 回答
1

您可以通过将 nativeQuery 设置为 true 来实现:

@Query(nativeQuery = true,
            value = "SELECT TOP 25 * FROM Arcust a WHERE a.arcustno <= :arcustno ORDER BY a.arcustno DESC")
List<Arcust> findByTop(String arcustno);
于 2017-10-31T03:13:06.297 回答
1

我知道这是 6 岁的请求,但这可能对仍有类似问题的人有所帮助。

在本机 sql 中,我们使用本机查询限制我们的结果集,例如

SELECT firstName, lastName,  FROM Student ORDER BY studentNumber LIMIT 1;

但是 JPA 不识别LIMIT 关键字。相反,它使用 setMaxResults

如果您已经设置了实体对象,您可以使用 JPA sql 轻松过滤到前 25 名,语法如下

entitymanager.createquery("select a from  "your Entity Object"  a where a.id =: parameter order by a.Id).setParameter("id",paramvalue).setMaxResults(25).getResultList();

在你的情况下,这应该工作

entitymanager.createquery("SELECT a FROM Arcust a WHERE a.arcustno <= :'parameter' ORDER BY a.arcustno DESC).setparameter("arcustno",1).setMaxResults(25).getResultList();
于 2020-03-04T20:17:24.880 回答