Spring Data REST - 如何在投影中包含计算数据?

Cha*_*lie 6 java spring spring-data-jpa spring-data-rest spring-boot

我定义了以下域类.

贷款类

@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;
}
Run Code Online (Sandbox Code Playgroud)

津贴类

@Data
@Entity
public class Allowance {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private AllowanceType allowanceType;


    private Double allowanceAmount;

}
Run Code Online (Sandbox Code Playgroud)

我还为贷款类定义了一个投影界面,如下所示:

@Projection(name = "studyLoanSingle", types = {Loan.class})
public interface LoanProjection {

    String getLoanTitle();

    List<AllowanceProjection> getAllowances();

}
Run Code Online (Sandbox Code Playgroud)

现在我想在投影中包括贷款总额(通过迭代允许列表计算)并将其发送到UI.是否可以在Spring Data REST中执行此操作?

Cep*_*pr0 10

这里:

您可以@Value使用SpEL表达式在Projection中注释公开的属性以公开合成属性.甚至可以在其他Spring bean上调用方法并将目标移交给它以用于高级计算.

所以你必须创建一个LoanRepobean方法(例如)来计算给定贷款的总金额:

@Query("select sum(a.allowanceAmount) as amount from Loan l join l.allowances a where l = ?1")
Double getTotalAmountByLoan(Loan loan);
Run Code Online (Sandbox Code Playgroud)

并使用像这样的投影:

@Projection(name = "totalAmount", types = Loan.class)
public interface LoanTotalAmount {

    @Value("#{target}")
    Loan getLoan();

    @Value("#{@loanRepo.getTotalAmountByLoan(target)}")    
    Double getAmount();
}
Run Code Online (Sandbox Code Playgroud)

然后你可以获得总额的贷款:

GET http://localhost:8080/api/loans?projection=totalAmount
Run Code Online (Sandbox Code Playgroud)

一切看起来都不错,但我们这里有一个"小"问题 - 对于结果中的每条记录,我们得到一个额外的查询到DB计算总金额.所以你面对的是' N + 1查询问题 '.

我可以在这里找到有关ProR的SDR问题的调查.

  • 您可以对分页结果进行单独的投影,以避免 N + 1 查询问题 (2认同)