我将如何在 Spring 数据存储库中编写 SELECT TOP 25 sql 查询

Posted

技术标签:

【中文标题】我将如何在 Spring 数据存储库中编写 SELECT TOP 25 sql 查询【英文标题】:How would I write SELECT TOP 25 sql query in Spring data repository 【发布时间】:2013-08-17 15:16:16 【问题描述】:

一个简单的问题,因为我确信这很愚蠢。我有以下可以在 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]

【问题讨论】:

【参考方案1】:

# 纯 SQL

使用“限制”

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

注意:JPA 支持使用 createNativeQuery() 方法或使用注释 @NamedNativeQuery 创建 Native 查询 JPA Native Query select and cast object 对象


#JPA

List<Arcust> findTop25ByArcustnoLessThanOrderByArcustnoDesc(String arcustno);

【讨论】:

【参考方案2】:

我不确定 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 doesn't support "limit"

【讨论】:

JPA 支持使用方法 createNativeQuery() 或使用注解 @NamedNativeQuery 来创建本机查询【参考方案3】:

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

在 spring-data 中你也可以使用原生查询: 对于 MySQl 可能有效:@Query(value="SELECT * FROM ARCUST_BIG WHERE arcustno&lt;='300000' ORDER BY arcustno DESC Limit 0, 25", nativeQuery=true)

但是,对于 Oracle-DB,您必须使用类似:@Query(value="SELECT * FROM ARCUST_BIG WHERE rownum&lt;=25 and arcustno&lt;='300000' ORDER BY arcustno DESC", nativeQuery=true)

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

【讨论】:

【参考方案4】:

我会说你需要

List<Arcust> findTop25ByArcustnoLessThanOrderByArcustnoDesc(String arcustno);

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

我实现的是 CrudRepository 而不是 JpaRepository

【讨论】:

【参考方案5】:

您可以通过将 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);

【讨论】:

【参考方案6】:

您可以在存储库中使用您的查询,无需 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();

【讨论】:

【参考方案7】:

我知道这是 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();

【讨论】:

这实际上是 6.5 岁的请求 :)

以上是关于我将如何在 Spring 数据存储库中编写 SELECT TOP 25 sql 查询的主要内容,如果未能解决你的问题,请参考以下文章

当我在存储库中编写一些 JPA 查询时,Spring 启动停止

在 spring data jpa 存储库中搜索许多可选参数

如何通过在spring数据本机查询或存储库中传递userIds列表来获取用户的最大日期时间戳

如何从 Spring Cloud 配置服务器存储和访问 html 文件?

如何在 jpa spring 存储库中使用 OrderBy?

是否可以在 Spring 存储库中使用原始 SQL