spring jpa 實現標籤過濾

呼~,總算搞出來了這個功能,開始覺得搞不出來只是由於對jpa的各類接口不熟悉,但在這周換了方案搞時才發現事情沒那麼簡單——本身對sql瞭解的也很膚淺!mysql

虛假的解決辦法

試題和標籤多對多,能夠選擇多個標籤來查找擁有這些標籤的試題,開始的想法是找出須要查詢的標籤,而後找出試題的標籤,前者所有在後者中便是要查詢的結果,理想很豐滿:sql

Subquery returns more than 1 row

mysql 並不支持本身這樣操做。ui

真正的解決辦法

上面的路行不通,本身又想不到其餘思路(還有曲線救國,先查詢再過濾,先不論效率,這是分頁查詢,因此就不能用這個方法),只能問潘老師,潘老師給出瞭解決辦法:debug

查詢時嘗試使用 count結合 in的方式,本身寫HSQL語句

count與in的結合

如果沒接觸過,對於這句話多是懵的,由於本身開始就是,count用於計算查詢出來的數據條數,他和in有什麼聯繫?code

讓咱們看看解決這個問題的sql(tag爲標籤,subject爲試題)接口

select
        subject0_.id 
    from
        subject subject0_ 
        #將表進行鏈接
    inner join
        subject_tags tags1_ 
            on subject0_.id=tags1_.subjects_id 
    inner join
        tag tag2_ 
            on tags1_.tags_id=tag2_.id 
    where
        tag2_.id in (
           # 查詢的tagId
            4,5
        ) 
    group by
        subject0_.id 
    having
    # 這裏須要等於查詢的tagId的數量
        count(subject0_.id)=2

關鍵就在於:查詢的tagId有幾個就須要查詢出幾條結果,由於須要每一個查詢條件都知足才能符合查詢要求。ci

sql語句對應的Hibernate的查詢寫法:get

public Page<Subject> pageAllByCurrentUser(Pageable pageable, Long courseId, Long modelId, Integer difficult, List<Long> tagIds) {
        return subjectRepository.findAll((Specification<Subject>) (root, query, builder) -> {
             ……
            if (tagIds != null && tagIds.size() > 0) {
                ListJoin<Subject, Tag> subjectTagListJoin = root.joinList("tags", JoinType.INNER);
                predicate = subjectTagListJoin.get("id").in(tagIds);
                logger.debug("進行分組");
                query.groupBy(root.get("id"));
                logger.debug("每一個條件都會查出一條相應的數據");
                query.having(builder.equal(builder.count(root.get("id")), tagIds.size()));
            }

            return predicate;
        }, pageable);
    }
相關文章
相關標籤/搜索