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

时间:2013-08-15 12:24:57

标签: java sql spring-data

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

7 个答案:

答案 0 :(得分:13)

我会说你需要

List<Arcust> findTop25ByArcustnoLessThanOrderByArcustnoDesc(String arcustno);

那将使用JPA并且可能适用于所有数据库,将开始使用SPRING JPA 1.7.0(Evans发布列车)

我实现了CrudRepository而不是JpaRepository

答案 1 :(得分:9)

纯SQL

使用“限制”

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

<强> JPA

List<Arcust> findTop25ByArcustnoLessThanOrderByArcustnoDesc(String arcustno);

答案 2 :(得分:7)

我不确定拉克什的答案是否正确。他似乎在编写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"

答案 3 :(得分:2)

实际上&#34;限制&#34;在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 - 但我也无法使它工作,所以上面的&#34;解决方法&#34;可能会有帮助。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

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

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

Page<Arcust> arcusts = arcustRepository.findByTop(arcustno, PageRequest.of(0, 25));
List<Arcust> arcust = arcusts.getContent();

答案 6 :(得分:0)

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