如何通过使用标准 API 将其子实体的 属性 列入白名单来 select JPA 实体?
How to select a JPA Entity by whitelisting a property of its child Entity with the Criteria API?
我遇到了以下假设性问题:
使用条件API(而不是JPQL),并给定
一个 table 充满了 用户,每个用户有多个 汽车
@Entity
public class User {
@Id
private Long id;
@OneToMany
private Set<Car> cars;
}
@Entity
public class Car {
@Id
private Long id;
private String model;
}
一个 Set<String>
包含 车型:
Set<String> models = getThousandsOfModels();
How can I select the User
s having at least one Car
whose model
is in the models
Set ?
我读过很多 SO 答案,尝试了不同的方法(最有希望的似乎涉及使用 Expression<Collection<String>>
、使用 .in()
等创建谓词)但没有任何效果。
下面的代码起到了作用:
Set<String> models = getHundredsOfModels();
if (models.size()>1000) throw new TooManyResultsException(); // Oracle limit
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cQuery = cb.createQuery(User.class);
Root<User> user = cQuery.from(User.class);
List<Predicate> predicates = new ArrayList<Predicate>();
// This lines are the trick ------------------------------------------
Join<User, Car> usersCars = user.join("cars", JoinType.INNER);
Predicate p = usersCars.<String>get("model").in(models);
// ---------------------------------------------------------------------
predicates.add(p);
cQuery.select(user).where(predicates.toArray(new Predicate[predicates.size()]));
我遇到了以下假设性问题:
使用条件API(而不是JPQL),并给定
一个 table 充满了 用户,每个用户有多个 汽车
@Entity public class User { @Id private Long id; @OneToMany private Set<Car> cars; }
@Entity public class Car { @Id private Long id; private String model; }
一个
Set<String>
包含 车型:Set<String> models = getThousandsOfModels();
How can I select the
User
s having at least oneCar
whosemodel
is in themodels
Set ?
我读过很多 SO 答案,尝试了不同的方法(最有希望的似乎涉及使用 Expression<Collection<String>>
、使用 .in()
等创建谓词)但没有任何效果。
下面的代码起到了作用:
Set<String> models = getHundredsOfModels();
if (models.size()>1000) throw new TooManyResultsException(); // Oracle limit
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cQuery = cb.createQuery(User.class);
Root<User> user = cQuery.from(User.class);
List<Predicate> predicates = new ArrayList<Predicate>();
// This lines are the trick ------------------------------------------
Join<User, Car> usersCars = user.join("cars", JoinType.INNER);
Predicate p = usersCars.<String>get("model").in(models);
// ---------------------------------------------------------------------
predicates.add(p);
cQuery.select(user).where(predicates.toArray(new Predicate[predicates.size()]));