[英]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);
現在,我想在一張桌子上顯示我的所有交易(收入和支出)。 因此,我現在正在探索性能有效的解決方案,以便在應用過濾器和分頁后從這兩個表中獲取數據。
我想使用規范,因為過濾器(數量、日期等)是可選的。
我可以想到以下方法:
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
或者是否有任何其他性能有效的解決方案?
您還有另一個選擇,即使用@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.