2014-10-02 47 views
1

在我的申請,我有以下兩個實體之間的映射:JPA標準查詢與運營商設置<?>與Spring DATA-JPA

@Entity 
public class Applicant { 
    private Integer id; 
    .... 
    private Set<Document> documents; 

    ... Getters and Setters ... 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "applicant", cascade = CascadeType.ALL) 
    public Set<Document> getDocuments() { 
    return documents; 
    } 

    public Applicant setDocuments(Set<Document> documents) { 
     this.documents = documents; 
     return this; 
    } 
} 

和文檔:

public class Document { 

    private Long id; 
    private Applicant applicant; 

    ... Getters and Setters ... 

    @ManyToOne 
    public Applicant getApplicant() { 
     return applicant; 
    } 

    public Document setApplicant(Applicant applicant) { 
     this.applicant = applicant; 
     return this; 
    } 
} 

我想使用Spring Data Specification(org.springframework.data.jpa.domain)以findAll(Spec spec)方法過濾我的ApplicantRepository中的某些申請人。

但是,我的問題是我想創建一個規範女巫採取參數設置和建立一個規範,以過濾申請人誰沒有鏈接到一個(不是全部)本文件。

我嘗試過不同的事情,但他們都沒有工作......我不知道我是否忘記了一些東西。 第一種是使用criteriaBuilder和值的方法...

public static Specification<Applicant> applicantHasDoc(final Set<Document> documents) { 
     return new Specification<Applicant>() { 
      @Override 
      public Predicate toPredicate(Root<Applicant> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       /* 
        Problem during parsing the query : 
        select * 
        from 
         applicant applicant0_ cross join document documents1_ 
        where 
         applicant0_.id=documents1_.applicant 
         and (. in (? , ?)) 
       */ 
       Expression<Set<Document>> documentExpression = root.get(Applicant_.documents); 
       return cb.in(documentExpression).value(documents); 
     }; 
    } 

這是返回一個GrammarSQL例外......你可以看到在代碼中的SQL查詢(簡體申請人字段)。

第二種解決方案是直接在申請人的ROOT使用元模型,並在:

public static Specification<Applicant> applicantHasDoc(final Set<Document> documents) { 
     return new Specification<Applicant>() { 
      @Override 
      public Predicate toPredicate(Root<Applicant> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       /*   
        Error with this type of criteria : Parameter value [[email protected]] did not match expected type [java.util.Set (n/a)] 
       */ 
        return root.get(Applicant_.documents).in(documents); 
      } 
     }; 
    } 

我已經在代碼中添加的每個解決方案的結果......和他們沒有工作。

本規範的主要目的是與他人使用這樣的:

List<Applicant> applicants = findAll(where(applicantHasDoc(documents).and(otherSpec(tags)).and(anotherSpec(mobilities), page); 

這樣我就可以在Spring數據JPA規範內才起作用。

其他信息:我正在使用H2數據庫。

感謝您的幫助。

回答

3

我找到了正確的方法來做到這一點,並且我所有的嘗試都很糟糕,因爲我一直在思考「像對象」而不是SQL ......但是CriteriaQuery是構建SQL查詢的「對象包裝器」。

所以,我寫我要在SQL查詢中,我找到了解決辦法:

我想在SQL是什麼:

select * 
from applicant applicant0_ inner join document documents1_ on applicant0_.id=documents1_.applicant where documents1_.id in (? , ?) 

所以我斷言似乎是以下幾點:

public static Specification<Applicant> applicantHasDoc(final Set<Document> documents) { 
     return new Specification<Applicant>() { 
      @Override 
      public Predicate toPredicate(Root<Applicant> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       SetJoin<Applicant, Document> documentApplicantJoin = root.join(Applicant_.documents); 
       return documentApplicantJoin.in(documents); 


      } 
     }; 
    }