2012-08-09 70 views
3

我有以下ManyToMany映射。@ManyToMany JPA 2複雜查詢

@Entity 
public class Class1 { 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

@ManyToMany(fetch = FetchType.LAZY) 
@JoinTable(name = "class1_class2", joinColumns = @JoinColumn(name = "class1Id"), inverseJoinColumns = @JoinColumn(name = "class2Id")) 
private List<Class2> class2; 
} 

@Entity 
public class Class2 { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 
} 

我想檢索所有Class1的實體,有關係有Classe2實體,與class2Id = 1和class2Id = 2和class2Id = 3。 {1,2,3}

或者篩選那些對他們的等級2列出Classe1的實體,該實體的Class2與值:class2Id = 1和class2Id = 2和class2Id = 3

例如:

如果在連接表上,我已經得到了以下值。

class1Id class2Id 
    1   1 
    1   2 
    1   3 
    1   4 
    6   1 
    6   2 
    6   3 
    4   1 
    5   2 

其結果將是在這個例子中,用的Class1 class1Id:1和6 因爲Class1的實體,與class1Id = 1具有與relaion classe2Id:1,2,3,4 及1級實體,與class1Id = 2與classe2Id有關聯:1,2,3

是否有可能使用JPA2(Predicate)返回正確的實體?

有沒有更好的映射來處理這種情況?

就目前而言,我想出了下面的SQL查詢:

select v1.class1Id from class1_class2 v1 
inner join class1_class2 v2 on v1.class1Id=v2.class1Id 
inner join class1_class2 v3 on v2.class1Id=v3.class1Id 
where v1.classe2Id=1 and v2.classe2Id=2 and v3.classe2Id=3; 
+0

你能澄清你的問題/例子嗎? – HRgiger 2012-08-09 21:50:15

+0

我已經添加了更多說明 – brianbro 2012-08-09 22:29:30

回答

4

下面是該查詢,可以幫助:

select c1 
from Class1 c1 
join c1.class2 c2 
where c2.id in (1,2,3) 
group by c1 
having count(c1)=3 ; 
1

還有一些地方是不是問題很清楚,因爲我沒有看到class1Id = 2中加入表值或class1Id = 6了只是class2Id = 1。但無論如何,我會給你類似的謂詞映射的例子,所以你可以修改你的需求。我用過StaticMetaModels。您可以將它們移動到實體類的相同包中。我無法測試課程,但我相信這可能是一個很好的路線圖。

JPA 2.0查詢:

 CriteriaBuilder criteriaBuilder = getEm().getCriteriaBuilder(); 

    CriteriaQuery<Class1> criteriaQuery = criteriaBuilder.createQuery(Class1.class); 

    Root<Class1> fromClass1 = criteriaQuery.from(Class1.class); 

    List<Predicate> conditions = new ArrayList<Predicate>(); 

    Subquery<Class2> qry = criteriaQuery.subquery(Class2.class);      

    Root<Class2> fromClass2 = qry.from(Class2.class); 

    qry.select(fromClass2); 

    qry.where(criteriaBuilder.equal(fromClass2.get(Class2_.getId()), idParamGoesHere)); 

    conditions.add(criteriaBuilder.in(.get(Class1_.getClass2()).value(qry)); 

    criteriaQuery.where(conditions.toArray(new Predicate[0])); 

    TypedQuery<Class1> query = getEm().createQuery(criteriaQuery); 

    List<Class1> results = query.getResultList(); 

StaticMetaModel的Class1:(不需要這種情況下,但我已經添加)

@StaticMetamodel(Class1.class) 
public class Class1_ { 

    private static volatile SingularAttribute<Class1, Long> id; 
    private static volatile SingularAttribute<Class1, Class2> class2; 

public static SingularAttribute<Class1, Long> getId() { 
     return id; 
    } 
    public static void setId(SingularAttribute<Class1, Long> id) { 
     Class1_.id = id; 
    } 
    public static SingularAttribute<Class1, Class2> getClass2() { 
     return class2; 
    } 
    public static void setClass2(SingularAttribute<Class1, Class2> class2) { 
     Class1_.class2 = class2; 
    } 
} 

StaticMetaModel等級2:

@StaticMetamodel(Class2.class) 
public class Class2_ { 

    private static volatile SingularAttribute<Class2, Long> id; 

public static SingularAttribute<Class2, Long> getId() { 
     return id; 
    } 
    public static void setId(SingularAttribute<Class2, Long> id) { 
     Class2_.id = id; 
    } 
} 
+0

嗨,對於class1Id = 2不需要。和class1Id = 6有class2Id = 1和2和3. – brianbro 2012-08-09 23:29:36

+0

嗨,我看到,你已經更新,希望它會有所幫助 – HRgiger 2012-08-09 23:34:17

+0

你的解決方案不起作用,因爲in clause reuturn entries with class1Id = 4 and 5 – brianbro 2012-08-10 00:22:35

3

首先,在你的類的Class2你需要添加以下內容:

@ManyToMany(fetch = FetchType.LAZY, mappedBy="class2") 
private List<Class1> class1; 

在這之後你的任務應該與此查詢來完成:

select c1 from Class1 c1 join c1.class2 c2 where c2.id in ?1 group by c1 

其中1 - 類型的對象? List<Long>,包含ID {1,2,3}

+0

爲什麼要添加與class2的關係呢?它的uniderectional關係您的查詢是不完整的。回答! – brianbro 2012-08-10 18:23:22

+0

實際上你並沒有指定你的查詢應該是單向的。無論如何,這個查詢也適用於單向映射。 – 2012-08-10 19:14:14