PlayFramework - 按 OneToMany 关系的最后一个条目排序的页面
PlayFramework - Page Sort by last Entry of OneToMany Relationship
我有以下结构:
public class ConversationModel extends Model {
@Id
public Long id;
@OneToMany(mappedBy="conversation", cascade= CascadeType.ALL)
public List<EventModel> events;
}
和
public abstract class EventModel extends Model {
@Id
public Long id;
public Date time;
}
现在,当我从对话模型中获取页面时,我想按数组事件中 EventModel 的最新条目对它们进行排序。
我试过类似的东西:
return find.where().disjunction()
.add(Expr.ilike("name", "%" + filter + "%"))
...
.orderBy("events.time desc, " + sortBy + " " + order)
.findPagedList(page, pageSize);
但这不知何故 returns 每个事件的分页列表中的 ConversationModel 条目。 (例如,如果有 3 个事件,则同一个对话重复 3 次)
如果我在 orderBy 查询中省略 "events desc",我会得到想要的结果,但排序不正确。
我也尝试在查询中设置 .setDistinct(true)
,但是 returns "Invalid SQL Syntax".
如何将我的所有对话排序到他们的最新事件条目?
感谢您的帮助。
编辑:
我设置了一个示例项目,它显示了问题:
https://github.com/dominik-ziegler/play-page-sort
应用程序首次启动时将对话打印到控制台:
[debug] - application - Conversation: First Conversation; ID1
[debug] - application - Conversation Last Message: Tue Jan 12 23:03:55 CET 2016
[debug] - application - ----------
[debug] - application - ----------
[debug] - application - Conversation: Second Conversation; ID2
[debug] - application - Conversation Last Message: Tue Jan 12 23:03:55 CET 2016
[debug] - application - ----------
[debug] - application - ----------
[debug] - application - Conversation: Third Conversation; ID3
[debug] - application - Conversation Last Message: Tue Jan 12 23:03:55 CET 2016
[debug] - application - ----------
但是根据插入日期顺序应该是:
- 第二次对话
- 第三次对话
- 第一次对话
在您的 ConversationModel
中,您可以使用 @javax.persistence.OrderBy
注释该字段,即:
@OneToMany(mappedBy="conversation", cascade= CascadeType.ALL)
@OrderBy("time DESC")
public List<EventModel> events;
它会做你需要的事情 - 将根据你的意愿对事件进行排序,而无需触及主要排序(因此你可以在查找查询中为对话添加其他排序)。
编辑:要实现您想要的效果,您需要使用
执行查询
GROUP BY conversation.id
和 ORDER BY event.id
:
(MySQL伪代码):
SELECT c.id c0, e.id FROM conversation c
LEFT OUTER JOIN event e ON c.id = e.conversation_id
WHERE lower(c.name) LIKE '%foo%'
GROUP BY c.id
ORDER BY e.id DESC;
不幸的是,裸露的 Finder 不允许您这样做,但您可以使用自己的 WHERE
构建 PagedList
并添加分组,例如:
PagedList<ConversationModel> convsPage = Ebean
.createQuery(
ConversationModel.class,
"WHERE lower(name) like :search GROUP BY id"
)
.setParameter("search","%"+filter+"%")
.order("events.id DESC")
.findPagedList(page, pageSize);
我有以下结构:
public class ConversationModel extends Model {
@Id
public Long id;
@OneToMany(mappedBy="conversation", cascade= CascadeType.ALL)
public List<EventModel> events;
}
和
public abstract class EventModel extends Model {
@Id
public Long id;
public Date time;
}
现在,当我从对话模型中获取页面时,我想按数组事件中 EventModel 的最新条目对它们进行排序。
我试过类似的东西:
return find.where().disjunction()
.add(Expr.ilike("name", "%" + filter + "%"))
...
.orderBy("events.time desc, " + sortBy + " " + order)
.findPagedList(page, pageSize);
但这不知何故 returns 每个事件的分页列表中的 ConversationModel 条目。 (例如,如果有 3 个事件,则同一个对话重复 3 次) 如果我在 orderBy 查询中省略 "events desc",我会得到想要的结果,但排序不正确。
我也尝试在查询中设置 .setDistinct(true)
,但是 returns "Invalid SQL Syntax".
如何将我的所有对话排序到他们的最新事件条目?
感谢您的帮助。
编辑:
我设置了一个示例项目,它显示了问题:
https://github.com/dominik-ziegler/play-page-sort
应用程序首次启动时将对话打印到控制台:
[debug] - application - Conversation: First Conversation; ID1
[debug] - application - Conversation Last Message: Tue Jan 12 23:03:55 CET 2016
[debug] - application - ----------
[debug] - application - ----------
[debug] - application - Conversation: Second Conversation; ID2
[debug] - application - Conversation Last Message: Tue Jan 12 23:03:55 CET 2016
[debug] - application - ----------
[debug] - application - ----------
[debug] - application - Conversation: Third Conversation; ID3
[debug] - application - Conversation Last Message: Tue Jan 12 23:03:55 CET 2016
[debug] - application - ----------
但是根据插入日期顺序应该是:
- 第二次对话
- 第三次对话
- 第一次对话
在您的 ConversationModel
中,您可以使用 @javax.persistence.OrderBy
注释该字段,即:
@OneToMany(mappedBy="conversation", cascade= CascadeType.ALL)
@OrderBy("time DESC")
public List<EventModel> events;
它会做你需要的事情 - 将根据你的意愿对事件进行排序,而无需触及主要排序(因此你可以在查找查询中为对话添加其他排序)。
编辑:要实现您想要的效果,您需要使用
执行查询
GROUP BY conversation.id
和 ORDER BY event.id
:
(MySQL伪代码):
SELECT c.id c0, e.id FROM conversation c
LEFT OUTER JOIN event e ON c.id = e.conversation_id
WHERE lower(c.name) LIKE '%foo%'
GROUP BY c.id
ORDER BY e.id DESC;
不幸的是,裸露的 Finder 不允许您这样做,但您可以使用自己的 WHERE
构建 PagedList
并添加分组,例如:
PagedList<ConversationModel> convsPage = Ebean
.createQuery(
ConversationModel.class,
"WHERE lower(name) like :search GROUP BY id"
)
.setParameter("search","%"+filter+"%")
.order("events.id DESC")
.findPagedList(page, pageSize);