[英]How to write an efficient JPQL query that returns list of linked records in a table?
这是我的后端JPA(ORM)结构:
MessageObject.java
messageId
messageName
relatedMessageId // maps to NEXT message in chain
假设消息名称中有一些内容表明它是链中我应该收到的第一条消息(即messageName为“ Create Message”)。
如何编写JPQL查询,该查询将基于名称为“ Create Message”的消息按顺序返回消息,并根据初始结果中的referencedId值返回下一个消息? 是否有一种更有效的方法来执行流操作,或者我的数据模型结构中存在缺陷?
这不是JPQL问题,而是数据库设计问题。 不同的数据库会有所不同,但通常关系数据库没有基于递归父级进行选择的简便方法。
有几种方法可以解决此问题:
------------------------------------------------------------------
| messageId | messageName | relatedMessageId | rootId | sequence |
------------------------------------------------------------------
| 1 | create | null | 1 | 1 |
| 2 | process | 1 | 1 | 2 |
| 3 | ship | 2 | 1 | 3 |
------------------------------------------------------------------
使用这样的表,您可以轻松获取所有创建消息“ where relatedMessageId IS null”。 如果您只需要使用rootId和序列来全部选择它们,则需要按顺序排列链中的所有消息。
----------------------------------------------------------------
| messageId | messageName | relatedMessageId | path |
----------------------------------------------------------------
| 1 | create | null | 000>001 |
| 2 | process | 1 | 000>001>002 |
| 3 | ship | 2 | 000>001>003 |
----------------------------------------------------------------
这种方法有点古怪且难以维护,但在速度上有一些好处。 这个想法是在varchar字段中的每个记录中保留id的路径。 有了它,您可以选择“ where path like LIKE'000>%'ORDER BY path”,它将按顺序在树状列表中选择所有记录。 要获得单个序列,只需将like查询更改为“ where path LIKE'000> 001>%'ORDER BY path”。 同样,这种方法很古怪且难以正确维护路径,但是由于您可以选择单个查询而不是多个查询来选择所有子级,因此它可以在以后获得回报。
对...有多种选择。 我在这里说一个。
我了解您有一个具有messageId和relatedMessageId列的“邮件”表。 您的表将与自身建立自相关关系,即relatedMessageId是messageId的前导键。
您的实体看起来像这样...
@Entity
public class Transaction implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer messageId;
@OneToMany(mappedBy = "relatedMessage")
private List<Message> relatedMessages = new ArrayList<>();
@ManyToOne
@JoinColumn(name = "relatedMessageId")
private Message parentMessage;
// constructors, aux methods, getter and setters
现在,您的JQL看起来像...
select m from Message m where m.parentMessage IS NULL
这将带来所有重要信息。 由此您可以...
List<Message> parentMessages = messageRepoInstance.findParentMessages();
for(Message message : parentMessages) {
List<Message> relatedMessages = message.getRelatedMessages();
}
抱歉,这全是我的想法,但我相信我设法通过了这个想法。 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.