英文:
How can you put your LIMIT inside a subquery in JPQL?
问题
// 假设您有一个名为 'entityManager' 的 EntityManager
int limit = 3;
int offset = 3;
String jpql = "SELECT u FROM User u ORDER BY u.id";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
query.setMaxResults(limit);
query.setFirstResult(offset);
List<User> users = query.getResultList();
// 如果您想要颠倒返回列表的顺序
Collections.reverse(users);
英文:
Are queries like this
SELECT *
FROM (
SELECT *
FROM users
ORDER BY id
LIMIT 3
OFFSET 3
) sub
ORDER BY id DESC;
translatable into JPQL? I'm not sure since LIMIT
and OFFSET
, which are not supported directly inside a JPQL string, are placed inside a subquery. The problem with setMaxResults()
and setFirstResult()
is that the associated SQL keywords are going to be appended to the outermost query whatever you do, it is not customizable
My LIMIT
, OFFSET
and GROUP BY
values are actually dynamic and represent pagination parameters passed in an HTTP request. I know OFFSET
is not very good for pagination, but even if you replace it with WHERE
, you're still left with LIMIT
that should still be inside a subquery
How do I turn that SQL into JPQL?
P.S.: In case you're wondering why I need LIMIT
and OFFSET
inside a subquery, you may visit this page
UPD: Here's ChatGPT-4's suggestion
// Assuming you have an EntityManager named 'entityManager'
int limit = 3;
int offset = 3;
String jpql = "SELECT u FROM User u ORDER BY u.id";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
query.setMaxResults(limit);
query.setFirstResult(offset);
List<User> users = query.getResultList();
// If you want to reverse the order of the returned list
Collections.reverse(users);
答案1
得分: 1
我认为你上面提到的解决方案应该可以工作。
如果不行,那么我会尝试这样做。假设你有一个User.java类和一个SessionFactory,我认为你可以创建一个像这样的方法:
public List<User> fetchUsersWithOffsetAndLimit(SessionFactory session, int offset, int limit) {
List<User> userList = session.getCurrentSession().createQuery(From User)
.setFirstResult(offset)
.setMaxResults(limit)
.list();
List<User> usersSortedByOrderIdDesc = new ArrayList<>();
for (int i = userList.size(); i > 0; i--) {
usersSortedByOrderIdDesc.add(userList.get(i));
}
return usersSortedByOrderIdDesc;
}
// SessionFactory sessionFactory = HibernateUtils.getLocSessionFactory();
// Session session = sessionFactory.getCurrentSession();
我添加了可以在参数内调用的SessionFactory。如果你没有在方法调用内传递它,你也可以将它添加到方法内。
可能有一种更有效的方法来做这件事,但我认为这个方法会起作用。
英文:
I think the solution you have above would work.
If not, then I would try this. Assuming you have a User.java class, and a SessionFactory, I believe you can create a method like this:
public List<User> fetchUsersWithOffsetAndLimit(SessionFactory session, int offset, int limit) {
List<User> userList = session.getCurrentSession().createQuery(From User)
.setFirstResult(offset)
.setMaxResults(limit)
.list();
List<User> usersSortedByOrderIdDesc = new ArrayList<>();
for (int i = userList.size(); i > 0; i--) {
usersSortedByOrderIdDesc.add(userList.get(i));
}
return usersSortedByOrderIdDesc;
}
// SessionFactory sessionFactory = HibernateUtils.getLocSessionFactory();
// Session session = sessionFactory.getCurrentSession();
I added the SessionFactory that can be called within the parameter. It can be added within the method if you are not passing it inside the method call.
There may be a more efficient way of doing it but I think this will work.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论