首页 > 解决方案 > 在 Spring Data JPA Repository 的 JPQL 查询中返回 ManyToOne 列表

问题描述

我有一个相对简单的领域模型,涉及使用 PostgreSQL 的 Spring Boot 2 应用程序中的书籍。

简单的情况是多本书属于一个系列(有排序),例如指环王 1、指环王 2 等。

我的域实体是

@Entity
@Table(name = "seriesentity")
public class SeriesEntity {    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(nullable = false)
    private String title;

    @OneToMany(mappedBy = "series")
    @OrderColumn(name = "series_index")
    private List<BookEntity> books;

    //Getters and Setters left out
}

@Entity
@Table(name = "book")
public class BookEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(nullable = false)
    private String title;

    @ManyToOne
    @JoinColumn(name="series_id")
    private SeriesEntity series;

    //Getters/setters and other unimportant properties left out
}

还有一个“DTO”,我想直接从数据库中检索它,然后我可以在前端使用它:

public class SeriesDto {
    private Long id;
    private String title;
    private Locale locale;
    private List<Book> books;

    public SeriesDto(Long id, String title, Locale locale, List<Book> books) {
        this.id = id;
        this.title = title;
        this.locale = locale;
        this.books = books;
    }

    public static class Book {
        private Long id;
        private String title;

        public Book(Long id, String title) {
            this.id = id;
            this.title = title;
        }
    }
}

在没有书籍的情况下创建 dto(在 IntelliJ 的 JPA 控制台中测试):

SELECT new series.query.SeriesDto(s.id, s.title, s.locale) FROM SeriesEntity s WHERE s.id = :id

但是如何映射 OneToMany 关系?

SELECT distinct s.id as series_id, s.title, s.locale, books FROM SeriesEntity s INNER JOIN s.books books WHERE s.id = :id

这将返回多行,例如:

1   Lord of the Rings   de  46  Der Herr der Ringe Band 1: Die Gefährten    1   Lord of the Rings   de
1   Lord of the Rings   de  47  Der Herr der Ringe Band 2: Die zwei Türme   1   Lord of the Rings   de

另一个问题是它会再次返回系列信息,因为它链接到 Book 实体。

有没有办法在 JPQL 中自动聚合它,这样我就不必编写 Java 方法了?或者我至少可以提供一个映射功能吗?

谢谢!

标签: javaspringjpql

解决方案


你应该使用:

SELECT new series.query.SeriesDto(s.id, s.title, s.locale, s.books)
FROM SeriesEntity s 
WHERE s.id = :id

可以看到查询日志:cross join(你的是inner join)


推荐阅读