使用列表填充 Spring 数据投影

Populate Spring Data Projection with list

我有以下 3 个 JPA 实体:

@Entity
public class Invoice {

    private String number;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "invoice")
    private List<Line> lines;

}

@Entity
public class Article {

    private String code;

}

@Entity
public class Line {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "invoice_id")
    private Invoice invoice;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "article_id")
    private Article article;

}

我正在尝试编写一个 Spring 数据投影以包含发票编号列表及其商品代码,为此我创建了以下内容 class:

@Data
@AllArgsConstructor
public class InvoiceWithArticlesView {

    private String invoiceNumber;
    private List<String> articleCodes;

}

这是我的尝试之一,但没有成功,因为我在应用程序启动时遇到错误:

@Query("select new package.InvoiceWithArticlesView(i.number, l.article.code) from Invoice i join i.lines l where i.number in : invoiceNumbers")
List<InvoiceWithArticlesView> getInvoicesWithArticles(List<String> invoiceNumbers);

编辑: 这是我收到的错误:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'invoiceRepository' defined in package.InvoiceRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract java.util.List package.InvoiceRepository.getInvoicesWithArticles(java.util.List)! Reason: Validation failed for query for method public abstract java.util.List package.InvoiceRepository.getInvoicesWithArticles(java.util.List)!; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List package.InvoiceRepository.getInvoicesWithArticles(java.util.List)!

我不确定这个答案是否足够好,但请尝试下一步。 你的查询很好。问题出在投影 class(构造函数)中。

首先,将吸气剂添加到所有实体 class,因为投影 class 将使用它们。

下一步更改 InvoiceWithArticlesView 投影 class 下一种方式:

@Data
public class InvoiceWithArticlesView {

    private String invoiceNumber;
    private List<String> articleCodes = new ArrayList<>();

    public InvoiceWithArticlesView(String invoiceNumber, Collection<Line> lines) {
        this.invoiceNumber = invoiceNumber;
        lines.forEach(line -> articleCodes.add(line.getArticle().getCode()));
    }
}

并更改存储库方法:

@Query("select new package.InvoiceWithArticlesView(i.number, i.lines) from Invoice i join i.lines l where i.number in :invoiceNumbers")
List<InvoiceWithArticlesView> getInvoicesWithArticles(@Param("invoiceNumbers") List<String> invoiceNumbers);

因为,查询 return 行列表,您必须以某种方式提取。在此示例中,我将 List 发送到 ctr,遍历它们并添加代码以列出 articleCodes。

另外,您使用了命名参数,所以您必须添加@Param注解。