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

时间:2016-06-21 20:14:03

标签: java jpa data-structures linked-list

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

MessageObject.java

messageId
messageName
relatedMessageId // maps to NEXT message in chain

假设消息名称中有一些内容表明它是我应该在链中预期的第一条消息(即messageName是“Create Message”)。

如何编写一个JPQL查询,根据名称为“Create Message”的消息按顺序返回消息,并根据初始结果中引用的Id值返回下一个消息?有没有更有效的方法来使用流来执行此操作,或者我的数据模型结构中是否存在缺陷?

2 个答案:

答案 0 :(得分:1)

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

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

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

使用这样的表,您可以轻松获取“relatedMessageId为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路径。使用此选项,您可以选择“路径LIKE'000>%'ORDER BY路径”,它将在树状列表中按顺序选择所有记录。要获得单个序列,您只需将类似的查询更改为“其中路径LIKE'000> 001>%'ORDER BY路径”。同样,这种方法很古怪,难以正确地维护路径,但它可以在以后获得速度,因为您可以选择所有具有单个查询而不是多个查询的子项。

答案 1 :(得分:1)

正确......有各种各样的选择。我会在这里说一句。

我知道你有一个“message”表,它有一个messageId和一个relatedMessageId列。你的表与selfess的自身关系是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();
}

对不起,这一切都是我的头脑,但我相信我设法传递了这个想法。 :)