java - 如何使用join在spring data jpa和spring boot中添加计数字段

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

我正在使用 Spring boot 和 spring data 开发一个 Rest 库项目。 我有一本实体 Book,其中包含 BookCopies 的集合。

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String isbn;
    @NotNull
    private String title;

    @JsonIgnore
    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<BookCopy> copyList = new ArrayList<>();

...

@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
public class BookCopy {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String barcode;
    private String editor;
    private boolean available = true;

    @ManyToOne(fetch = FetchType.LAZY)
    private Book book;
...

我想执行一个请求,为我提供所有可用的书籍和副本数量。 我在标准 sql 中执行它没有问题:

select book.*, count(book_copy.id) as nb_copies from book
inner join book_copy on book.id = book_copy.book_id
where book.title like '%:title%' 
and book_copy.available = true
group by book.id

但我无法让它在我的项目中工作。 我以为我可以用jpql来做到这一点,但是当我尝试加入实体bookCopy时,intellij没有进行任何自动补全,这让我怀疑存在配置问题。如果我尝试“在控制台中运行查询”,它会告诉我“找不到运行程序”,即使我在 intellij 中设置了数据库。 我也尝试使用 native 查询来完成此操作,但它也不起作用。

我设法得到了结果,但我认为方法错误:

@Override
    public List<Book> findByTitle(String title) {
        List<Book> bookList = bookRepository.findByTitleLike("%"+title+"%");
        for(Book book:bookList){
            book.setCopyList(bookCopyRepository.findAllInBookWhereAvailable(book.getId(), true));
        }
        return bookList;
    }

这将启动对每本书的查询以获取副本列表。所以我没有想法,也无法获得很多明确的信息。 谢谢!

最佳答案

以下 JPQL 应返回与 native SQL 查询相同的数据集:

select b, count(c) from Book b
join b.copyList c
where b.title like :title and c.available
group by b

Java代码:

        String title = ...;
        final List result = em.createQuery("select b, count(c) from Book b" +
                " join b.copyList c " +
                " where b.title like :title and c.available " +
                " group by b ")
                .setParameter("title", title)
                .getResultList();
        for (Object res : result) {
            Object[]  row = (Object[]) res;
            System.out.println("Book: " + row[0]);
            System.out.println("BookCopy CNT: " + row[1]);
        }

关于java - 如何使用join在spring data jpa和spring boot中添加计数字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58880075/

相关文章:

java - 在Java中创建一个弹出框

java - 下载 Eclipse 的源代码

java - 用于 Spring 安全的 SpEL : Passing Values from XML to Java based SpEL configuration

java - 如何确定要使用哪个 spring 上下文?

java - 我们如何接受多部分的请求主体?

java - 我如何使用 java、RestAssured 测试 Web 服务自动替换 Json 对象文件中的两个单独的 ID

java - 在 Java ArrayList 中搜索逗号分隔值 - 字符串和 int 组合。

java - 使 Spring Boot/actuator/heath 并行运行检查

java - Spring Security与Keycloak集成时遇到NullPointerException

java - 在为此目标 Web 运行测试用例之前,如何使用多线程启动 Web 应用程序?