我定义了以下域类。
贷款类
@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中执行此操作?
答案 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