如何通过 JPQL 将投影查询映射到具有 @ManyToMany @JoinTable 属性的 DTO

use*_*613 5 java hibernate jpa jpql spring-data-jpa

我有一个Blog实体,如:

@Entity
class Blog{
    @Id
    private Long id;

    private String titie;

    private String content;

    @ManyToMany
    @JoinTable(
        name = "blog_tag_association",
        joinColumns = @JoinColumn(name = "blog_id"),
        inverseJoinColumns = @JoinColumn(name = "tag_id")
    )
    private Set<Tag> tags = new LinkedHashSet<>();

    // ...
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我使用一个单独的表来代表之间的关系BlogTag

我已经阅读了这篇文章并编写了我的自定义 JPQL 查询以将我的查询结果映射到 DTO:

class BlogSummaryDTO{
    private Long id;

    private String title;

    private Set<Tag> tags;

    public BlogSummaryDTO(Long id, String title, Set<Tag> tags){
        this.id = id;
        this.title = title;
        this.tags = tags;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的自定义 JPQL 像:

String query = "SELECT new com.okatu.rgan.blog.model.BlogSummaryDTO(" +
    "b.id, b.title, " +
    "b.tags) FROM Blog b";
Run Code Online (Sandbox Code Playgroud)

它无法工作,终端告诉我:

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use near 'as col_2_0_ from blog blog0_ inner join blog_tag_association tags1_ on blog0_.id' at line 1
Run Code Online (Sandbox Code Playgroud)

它生成的 sql 是这样的:

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use near 'as col_2_0_ from blog blog0_ inner join blog_tag_association tags1_ on blog0_.id' at line 1
Run Code Online (Sandbox Code Playgroud)

如果我tags从 JPQL 和 DTO 的构造函数的参数列表中删除该属性,它运行良好。

那么我应该如何编写我的自定义 JPQL 来构造带有 @JoinTable 属性的 DTO?


我还观察到 jpa 生成的 sql 在执行时BlogRepository::findById,它使用单独的本机 sql 来检索Tag.

Hibernate: 
    select
        blog0_.id as col_0_0_,
        blog0_.title as col_1_0_,
        . as col_2_0_ 
    from
        blog blog0_ 
    inner join
        blog_tag_association tags1_ 
            on blog0_.id=tags1_.blog_id 
    inner join
        tag tag2_ 
            on tags1_.tag_id=tag2_.id 
    where
        blog0_.title like ? 
        or blog0_.title like ? limit ?
Run Code Online (Sandbox Code Playgroud)

但我不知道它生成的 JPQL 是什么。