繁体   English   中英

如何编写一个高效的JPQL查询,该查询返回表中链接记录的列表?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM