Reputation: 4769
I have got the following ManyToMany mapping.
@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;
}
I want to retrieve all the Class1 entities, that have relation with Classe2 entities, with class2Id = 1 and class2Id =2 and class2Id =3. {1,2,3}
Or to filter the Classe1 entities that have on their class2 List, the Class2 entities with the values: class2Id = 1 and class2Id =2 and class2Id =3
For example:
If on the join table, i have got the follwoing values.
class1Id class2Id
1 1
1 2
1 3
1 4
6 1
6 2
6 3
4 1
5 2
The result would be for this example, Class1 with class1Id: 1 and 6. Because Class1 entity, with class1Id=1 has relaion with classe2Id: 1,2,3, 4 And Class1 entity, with class1Id=2 has relaion with classe2Id: 1,2,3
Is it possible to get the right entities returned with JPA2 (Predicate)?
And is there any better mappings to handle this case?
For the moment, i have come up with the following SQL query:
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;
Upvotes: 3
Views: 6287
Reputation: 4769
Here is the query that can help:
select c1
from Class1 c1
join c1.class2 c2
where c2.id in (1,2,3)
group by c1
having count(c1)=3 ;
Upvotes: 4
Reputation: 2018
At first in your class Class2 you'll need add the following:
@ManyToMany(fetch = FetchType.LAZY, mappedBy="class2")
private List<Class1> class1;
After this your task should be done with this query:
select c1 from Class1 c1 join c1.class2 c2 where c2.id in ?1 group by c1
where ?1 - object of type List<Long>
, containing ids {1,2,3}
.
Upvotes: 3
Reputation: 2790
Still some parts are not very clear on question as I dont see class1Id=2 in join table values or class1Id=6 has just class2Id=1. But anyway I will give you similar predicate mapping example so you can modify for your needs. I have used StaticMetaModels. You can move them to the same package of your entity classes. I was not able to test ofcourse but I believe can be a good roadmap.
JPA 2.0 query:
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: (not needed for this case but i have added)
@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 Class2:
@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;
}
}
Upvotes: 1