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



这是我的后端JPA(ORM)结构:

MessageObject.java

messageId
messageName
relatedMessageId // maps to NEXT message in chain

假设消息名称中的某些内容表明这是我在链条中应该期望的第一条消息(即Messagename是"创建消息")。

我将如何编写一个jpql查询,该查询将基于名称为"创建消息"的消息返回消息,并根据初始结果中的引用值返回下一个消息?是否有更有效的方法可以通过流进行此操作,或者我的数据模型结构中存在缺陷?

这不是一个jpql问题,而是数据库设计问题。它会因数据库而异,但通常关系数据库基于递归父母而没有简单的选择。

有几种方法可以解决此问题:

------------------------------------------------------------------
| messageId | messageName | relatedMessageId | rootId | sequence |
------------------------------------------------------------------
| 1         | create      | null             | 1      | 1        |
| 2         | process     | 1                | 1      | 2        |
| 3         | ship        | 2                | 1      | 3        |
------------------------------------------------------------------

使用这样的表格,您可以轻松地获取所有创建消息" where RessionMessageId为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的路径。有了此,您可以选择"路径之类的路径>%'订单按路径",它将在像列表这样的树中选择所有记录。要获取一个序列,您只需将类似查询更改为"路径之类的路径> 001>%'订单的路径"。同样,这种方法是古怪的,很难正确地维护路径,但是以后它可以以速度回报,因为您可以选择一个单个查询而不是多个儿童。

对...有多种选择。我将在这里陈述一个。

我知道您有一个"消息"表,其中具有messageID和一个相关的messageID列。您的桌子将与自身相关的自我关系,这是消息ID的钥匙。

您的实体看起来像这样...

@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();
}

对不起,这全是我的头顶,但我相信我设法通过了这个想法。:)

最新更新