如果我有一个Spring存储库,则可以通过以下方式定义一个方法来获得分页结果(例如):
@Query("<some JPAQL here>")
Page<Person> findBySomething(String foo, String bar, Pageable pageable);
我想这样做,只是动态地创建查询(查询本身根据某些输入数据而略有不同)。像这样:
String queryString = "<JPAQL part1>";
if (condition) queryString += "<JPAQL part2>";
queryString += "<JPAQL part3>";
Query query = entityManager.createQuery(queryString);
query.setParameter("foo", foo);
query.setParameter("bar", bar);
return query.getResultListAndApplySpringPaging(pageable);
我不是想要将查询重写为Querydsl或Criteria API。部分原因是我不想花时间,部分原因是我的JPAQL包含一些Oracle特定的内容,这些内容可能很难表达(即使不是不可能)(例如ORDER BY NLSSORT(t.displayValue, 'NLS_SORT = XCZECH') ASC
之类)。 / p>
是否可以通过Spring的分页机制手动传递String
或javax.persistence.Query
?
答案 0 :(得分:0)
如果创建2个方法怎么办:一个带有part2的方法,一个没有part2的方法,然后根据条件调用适当的方法。
@Query("<part part3>")
Page<Person> findBySomething(String foo, String bar, Pageable pageable);
@Query("<part1 part2 part3>")
Page<Person> findBySomethingElse(String foo, String bar, Pageable pageable);
...
return condition?findBySomethingElse(foo, bar, pageable):findBySomething(foo, bar, pageable);
答案 1 :(得分:0)
因此,在调试Spring内部构件一段时间后,我得到了类似于解决方案的东西。它跳过了Spring所做的许多事情(这意味着它不那么普遍),但至少在简单的情况下,它似乎对我有用。
String queryString = dynamicallyComposeQueryForConditions(someConditions);
String countQueryString = QueryUtils.createCountQueryFor(queryString);
Query query = entityManager.createQuery(queryString);
Query countQuery = entityManager.createQuery(countQueryString);
query.setParameter("foo", foo);
query.setParameter("bar", bar);
countQuery.setParameter("foo", foo);
countQuery.setParameter("bar", bar);
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
return PageableExecutionUtils.getPage(query.getResultList(), pageable,
() -> (long) countQuery.getSingleResult());
显然,还有改进的空间。首先,两个查询都需要具有相同的参数集,出于简单起见,不应该像我在此处那样进行设置。第二,getPage
非常聪明,仅在需要时才执行countQuery
(或更确切地说totalSupplier
)(并非总是如此)。这意味着即使调用QueryUtils.createCountQueryFor(queryString)
然后再调用entityManager.createQuery(countQueryString)
也不总是必须的,实际上应该只在totalSupplier
内部进行。