簡體   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