我定义了以下域类。
贷款类别
@Data @Entity public class Loan { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String loanTitle; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "loan_id") private List<Allowance> allowances; }
津贴等级
@Data @Entity public class Allowance { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private AllowanceType allowanceType; private Double allowanceAmount; }
我还为贷款类定义了一个投影接口,如下所示:
@Projection(name = "studyLoanSingle", types = {Loan.class}) public interface LoanProjection { String getLoanTitle(); List<AllowanceProjection> getAllowances(); }
现在,我要在投影中包括贷款的总金额(通过对“津贴”列表进行迭代来计算),并将其发送到UI。在Spring Data REST中可以做到这一点吗?
从这里:
您可以@Value使用SpEL表达式对合成中的公开属性进行注释。甚至 调用 其他Spring Bean上的 方法 ,并将目标移交给该目标,以用于 高级计算 。
@Value
因此,您必须创建一个LoanRepobean方法(例如)来计算给定贷款的总额:
LoanRepo
@Query("select sum(a.allowanceAmount) as amount from Loan l join l.allowances a where l = ?1") Double getTotalAmountByLoan(Loan loan);
并使用像这样的投影:
@Projection(name = "totalAmount", types = Loan.class) public interface LoanTotalAmount { @Value("#{target}") Loan getLoan(); @Value("#{@loanRepo.getTotalAmountByLoan(target)}") Double getAmount(); }
然后,您可以获得总金额的贷款:
GET http://localhost:8080/api/loans?projection=totalAmount
一切看起来不错,但是这里有一个“小”问题-对于结果中的每条记录,我们都会向数据库额外查询以计算总金额。因此,您在此处面临“ N + 1个查询问题 ”。
我对带有投影的SDR中此问题的调查可以在这里找到。