簡體   English   中英

帶有兩個表的 Spring Data JPA 規范分頁

[英]Spring Data JPA Specification Paging with Two Tables

我有兩個表:收入和支出,我在其中存儲所有收入和支出交易,目前這兩個表之間沒有關系。

@Entity
@Table(name = "expense")
public class Expense {

    private BigDecimal amount;
    private LocalDate dueDate;
    private LocalDate datePaid;
    private String description;
    ......
}

@Entity
@Table(name = "income")
public class Income {

    private BigDecimal amount;
    private LocalDate dueDate;
    private LocalDate datePaid;
    private String description;
    ......
}

目前,我使用 Spring Data JPA 的規范功能在單個實體上執行此操作:

對於費用: Page<Expense> expensePage = expenseRepository.findAll(expenseSpecification, paginatedList);

對於收入: Page<Income> depositPage = incomeRepository.findAll(incomeSpecification, paginatedList);

現在,我想在一張桌子上顯示我的所有交易(收入和支出)。 因此,我現在正在探索性能有效的解決方案,以便在應用過濾器和分頁后從這兩個表中獲取數據。

我想使用規范,因為過濾器(數量、日期等)是可選的。

我可以想到以下方法:

  1. 如上所述單獨運行查詢,合並結果,然后手動應用分頁 - 從性能角度來看,這似乎非常無效,因為它將獲取整個表數據
  2. 將本機 SQL 查詢與 UNION 一起使用,但無法應用過濾器,因為過濾器是動態且可選的

select * from (SELECT id, amount,paid_on as "date_paid", 'EXPENSE' as "type" FROM public.expense UNION SELECT id, amount, received_on as "date_paid", 'DEPOSIT' FROM public.deposit) as annon_1 where annon_1 .amount > 2 and annon_1.date_paid = '2021-08-10' order by annon_1.id Limit 5 offset 0

  1. 實現繼承,因為收入和費用基本上都是事務,具有一些共享屬性,如日期、金額、描述等……但這將是一個很大的變化,因為這兩個表中已經有很多數據。 所以我必須更改數據庫架構、域類和遷移來管理現有數據

或者是否有任何其他性能有效的解決方案?

您還有另一個選擇,即使用@Subselect實體。

@Entity
@Subselect("select i.id as id, true as income, i.description as description, i.date_paid as date_paid, i.due_date as due_date, i.amount as amount from income i union all select e.id as id, false as income, e.description as description, e.date_paid as date_paid, e.due_date as due_date, e.amount as amount from expense e")
public class Transaction {
    @EmbeddedId
    private TransactionId id;
    @Column(name = "amount")
    private BigDecimal amount;
    @Column(name = "due_date")
    private LocalDate dueDate;
    @Column(name = "date_paid")
    private LocalDate datePaid;
    @Column(name = "description")
    private String description;
}

@Embeddable
public class TransactionId {
    @Column(name = "id", nullable = false)
    private Long id;
    @Column(name = "income", nullable = false)
    private boolean income;
}

然后,您可以像查詢收入和支出一樣查詢它。

最重要的是,我可以建議您為此目的使用 Blaze-Persistence,它在 JPA/Hibernate 之上工作,並添加對 UNION ALL 等集合操作的支持,以防您需要更動態地創建此 UNION,即基於更改查詢一些運行時條件。 我也認為這是Blaze-Persistence Entity Views的完美用例。

我創建了該庫以允許在 JPA 模型和自定義接口或抽象類定義模型之間輕松映射,例如 Spring Data Projections on steroids。 這個想法是您以您喜歡的方式定義您的目標結構(域模型),並通過 JPQL 表達式將屬性(getter)映射到實體模型。

使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

@EntityView(Transaction.class)
public interface TransactionDto {
    @IdMapping
    TransactionIdDto getId();
    String getDescription();
    LocalDate getDatePaid();
    LocalDate getDueDate();
    BigDecimal getAmount();

    @EntityView(TransactionId.class)
    interface TransactionIdDto {
        @IdMapping
        Long getId();
        boolean isIncome();
    }
}

查詢是將實體視圖應用於查詢的問題,最簡單的就是通過 id 進行查詢。

TransactionDto a = entityViewManager.find(entityManager, TransactionDto.class, id);

Spring Data 集成允許您幾乎像 Spring Data Projections 一樣使用它: https ://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<TransactionDto> findAll(Pageable pageable);

最好的部分是,它只會獲取實際需要的狀態!

使用本機查詢和內部查詢使用“UNION ALL”鍵從表中獲取數據。

SELECT 
    t3.*
FROM
    ((SELECT 
        t1.amount, t1.duedate, t1.datePaid, t1.description
    FROM
        EXPENSES t1) UNION ALL (SELECT 
        t2.amount, t2.duedate, t3.datePaid, t4.description
    FROM
        Income t2)) t3.

對於 JPA 查詢。

@Query(value = " SELECT t3.* FROM ((SELECT t1.amount, t1.duedate, t1.datePaid, t1.description FROM EXPENSES t1) UNION ALL (SELECT t2.amount, t2.duedate, t3.datePaid, t4.description FROM Income t2)) t3 ?#{#pageable}", countQuery = "SELECT count(*) FROM ((SELECT t1.amount, t1.duedate, t1.datePaid, t1.description FROM EXPENSES t1) UNION ALL (SELECT t2.amount, t2.duedate, t3.datePaid, t4.description FROM Income t2)) t3 ", nativeQuery = true)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM