英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论