【问题标题】:How to use LIMIT in spring within sql query?如何在 sql 查询中在 spring 中使用 LIMIT?
【发布时间】:2014-08-13 14:10:25
【问题描述】:

不知何故,我无法在使用 Spring-data-jpa 的 sql 查询中使用 LIMIT 限定符:

@Query("SELECT p from Person p WHERE p.company.id = :id ORDER BY p.name DESC LIMIT 3")

这里有什么问题?

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: Limit near line 1, column 146
    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:91)
    at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:109)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:304)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:203)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:126)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:88)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:190)
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1800)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:328)
    ... 48 more

【问题讨论】:

  • 五月this帮助。
  • 好吧,这至少可以工作,虽然我可以在 sql 语句中直接使用 LIMIT 关键字...
  • 我认为 LIMIT 是高度特定于供应商的。使用 JPA,您可以执行 q.setMaxResults(limitVal)
  • @membersound 您不是在编写 SQL,而是在编写 HQL。非常不同的东西。如果它是一个 SQL 查询,它会起作用,它在 HQL 中不起作用。

标签: java spring spring-data-jpa


【解决方案1】:

LIMIT 不是 JPQL 的一部分。当前版本(撰写本文时为 1.6.0.RELEASE)中可用的机制是分页:

interface PersonRepository extends Repository<Person, Long> {

  @Query("...")
  List<Person> findLimited(..., Pageable pageable);
}

然后可以按如下方式使用:

repository.findLimited(..., new PageRequest(0, 10));

这将返回@Query 注释中定义的查询的前十个结果。

Spring Data JPA 的当前主分支已经包含一个新功能,可以让您重写上述查询,如下所示:

interface PersonRepository extends Repository<Person, Long> {

  List<Person> findTop3ByCompanyOrderByName(Company company);
}

从版本 1.7.0.M1(snapshots 中的 already available 功能)开始,查询派生机制将理解 TopFirst 在主题子句中限制返回的结果数量。

更新 由于new PageRequest 已弃用,您需要改用PageRequest.of(0, 10)

【讨论】:

  • 如果我需要使用@Query,因为现有的派生机制还不够,但我仍然想限制结果的数量,该怎么办?像其他人说的那样在查询中放入TOP或LIMIT不起作用,在方法名称中放入TOP也不起作用,因为在使用Query时禁用了派生机制,我还应该使用分页方法吗?
【解决方案2】:

我的回复可能很晚,但如果我可以帮助其他人,您可以像这样使用 nativeQuery:

@Query(value="SELECT * from person p WHERE p.company_id = :id ORDER BY p.name DESC LIMIT 3", nativeQuery = true)

【讨论】:

  • 这非常适合我的 Spring Boot 2.3.6 项目。谢谢!
【解决方案3】:

另一种方法是使用 HQL 代替 Spring-data-jpa,然后使用 setMaxResults()

例如:

SessionFactory sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();

Query query = session.createQuery("FROM Person WHERE company.id = :id ORDER BY name DESC");
query.setParameter("id", id);
query.setMaxResults(3); // this replaces the LIMIT in the query
List<Person> personList = query.getResultList();

session.getTransaction().commit();
session.close();

【讨论】:

    猜你喜欢
    • 2018-11-14
    • 2019-12-04
    • 1970-01-01
    • 2011-08-31
    • 2014-10-08
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多