Как сопоставить проекционный запрос с DTO, у которого есть свойство @ManyToMany @JoinTable от JPQL - PullRequest
1 голос
/ 14 марта 2020

У меня есть сущность 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<>();

    // ...
}

Как вы можете видеть, я использую отдельную таблицу для представления отношений между Blog и Tag.

Я прочитал эту запись и написал свой собственный запрос 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;
    }
}

И мой собственный JPQL вроде:

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

Это не может работать, терминал сказал мне, что:

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

sql, которое он генерирует, было похоже на:

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 ?

Если я удаляю свойство tags из JPQL и DTO список параметров конструктора, он работает хорошо.

Так как мне написать свой собственный JPQL для создания DTO со свойством @JoinTable?


Я также наблюдал сгенерированный jpa sql когда BlogRepository::findById использует отдельный нативный sql для извлечения Tag.

Hibernate: 
    select
        blog0_.id as id1_0_0_,
        blog0_.content as content2_0_0_,
        blog0_.created_time as created_3_0_0_,
        blog0_.modified_time as modified4_0_0_,
        blog0_.summary as summary5_0_0_,
        blog0_.title as title6_0_0_,
        blog0_.author_id as author_i9_0_0_,
        user1_.id as id1_5_1_,
        user1_.created_time as created_2_5_1_,
        user1_.username as username7_5_1_,
    from
        blog blog0_ 
    left outer join
        user user1_ 
            on blog0_.author_id=user1_.id 
    where
        blog0_.id=?
Hibernate: 
    select
        tags0_.blog_id as blog_id1_1_0_,
        tags0_.tag_id as tag_id2_1_0_,
        tag1_.id as id1_4_1_,
        tag1_.description as descript2_4_1_,
        tag1_.title as title3_4_1_ 
    from
        blog_tag_association tags0_ 
    inner join
        tag tag1_ 
            on tags0_.tag_id=tag1_.id 
    where
        tags0_.blog_id=?

Но я не знаю, какой JPQL он сгенерировал.

...