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

时间:2017-07-23 02:51:37

标签: java spring spring-boot spring-data-jpa spring-data-rest

我定义了以下域类。

贷款类

@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();

}

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

2 个答案:

答案 0 :(得分:8)

来自here

  

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

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

@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

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

我使用Project在SDR中对此问题进行了调查,您可以找到here

答案 1 :(得分:1)

放置在域对象上解决视图表示(投影)的方法不是最佳解决方案。

放置在存储库中对于简单的用例非常有用,对于存在Java 8的复杂问题,由于@Projection(name = "studyLoanSingle", types = Loan.class) public interface LoanProjection { String getLoanTitle(); //If no need Allowances on json @JsonIgnore List<Allowance> getAllowances(); public default Double getAmount() { Double result = new Double(0); for (Allowance a : getAllowances()) { result += a.getAllowanceAmount(); } return result; } } 接口方法,您可以使用这个简单的技巧。

AttachmentData