java 使用 JPA Criteria API 查询 Enum 的 ElementCollection
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12092268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Query ElementCollection of Enum by using JPA Criteria API
提问by kungcc
I'm working of a web application for a car dealer. I have a Car class with a field which contain a set of security enums.
我正在为汽车经销商开发 Web 应用程序。我有一个包含一组安全枚举的字段的 Car 类。
public class Car {
@Id
@GeneratedValue
private Long id;
@NotNull(message = "{year}")
@Min(value = 1950)
@Max(value = 2020)
@Column(nullable = false)
private int year;
@NotNull()
@Column(nullable = false)
private String make;
@NotNull()
@Column(nullable = false)
private String model;
@NotNull()
@Min(value = 0)
@Max(value = 1000000)
@Column(nullable = false)
private int kilometres;
@Column(nullable = false)
private int price;
@NotNull()
@Enumerated(EnumType.STRING)
private Gearbox gearbox;
@ElementCollection(fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
@CollectionTable(name="SECURITY")
@Column(name="TYPE")
private Set<Security> securityList = new HashSet<Security>();
@NotNull()
@Column(nullable = false)
private String description;
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, orphanRemoval = true)
private List<Picture> pictureList = new ArrayList<Picture>();
// Getters and setters + help methods..
The Security enum is like:
安全枚举是这样的:
public enum Security {
ABS("abs"),
AIRBAG("airbag"),
ANTISPIN("antispin"),
CENTRAL_LOCKING("centralLocking"),
REMOTE_ALARM("remoteAlarm"),
FOUR_WHEEL("fourWheel"),
PARKING_ASSISTANCE("parkingAssistance"),
SERVICE_MANUAL("serviceManual"),
STABILITY_CONTROL("stabilityControl"),
XENON_LIGHT("xenonLight");
private String label;
private Security(String label) {
}
public String getLabel() {
return label;
}
}
In the web application, I will create a search page, where the users is able to define required Securitiy parts and a manufacturer pattern (make field in Car class) . For instance, a user might search for Cars which have a make pattern according to "Volkswagen" and Security with at least ABS and REMOTE_ALARM.
在 Web 应用程序中,我将创建一个搜索页面,用户可以在其中定义所需的安全部件和制造商模式(汽车类中的 make 字段)。例如,用户可能会根据“Volkswagen”和至少具有 ABS 和 REMOTE_ALARM 的安全性来搜索具有制造模式的汽车。
My problem is that I am not sure how to create the query using the criteria API. I guess it should start like:
我的问题是我不确定如何使用标准 API 创建查询。我想它应该像这样开始:
public List<Car> searchCars(String makePattern, Set<Security> requiredSecuirtySet) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Car> cq = cb.createQuery(Car.class);
Root<Car> _car = cq.from(Car.class);
// Give me some help here please =)
return em.createQuery(cq).getResultList();
}
Can you please help me? I also have a meta model over the Car class.
你能帮我么?我也有一个 Car 类的元模型。
Best regards and thanks in advance!
最好的问候并提前致谢!
采纳答案by kungcc
Thanks siebz0r!
谢谢 siebz0r!
I was modifying your code a little bit since your code returns all Cars that has 1 or more security (and not all), i.e. returns all cars which has a securityList that contain at least a subset of the securityList.
我正在稍微修改您的代码,因为您的代码返回所有具有 1 个或多个安全性(而不是全部)的汽车,即返回所有具有至少包含 securityList 子集的 securityList 的汽车。
Here is my code:
这是我的代码:
public List<Car> searchCars(String makePattern, Set<Security> requiredSecuirtySet) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Car> cq = cb.createQuery(Car.class);
Root<Car> car = cq.from(Car.class);
Predicate criteria = cb.conjunction();
for (Security security : carQueryData.getSecurityCriteria()) {
criteria = cb.and(criteria, car.get(Car_.securityList).in(security) );
}
// Add more predicates, for instance:
// for (Equipment equipment : carQueryData.getEquipmentsCriteria()) {
// criteria = cb.and(criteria, car.get(Car_.equipmentList).in(equipment) );
// }
Predicate makePredicate = cb.equal(car.get(Car_.make), makePattern);
cq.select(car).where(makePredicate, criteria);
return em.createQuery(cq).getResultList();
}
Best regards
最好的祝福
回答by siebz0r
You can use collections as parameters so maybe this will work:
您可以使用集合作为参数,所以这可能会起作用:
TypedQuery<Car> q = em.createQuery("select c from Car c where c.make = :make and c.securityList in :secutiryList", Car.class);
q.setParameter("make", makePattern);
q.setParameter("securityList", requiredSecuirtySet);
return q.getResultList();
I haven't tested this so I'm not sure it will work. It is based on this question. I also haven't worked with the criteria API so I didn't know how to 'translate' it.
我还没有测试过这个,所以我不确定它会起作用。它基于这个问题。我也没有使用过标准 API,所以我不知道如何“翻译”它。
Here's a shot at the query with the criteria API:
这是使用标准 API 进行查询的一个镜头:
public List<Car> searchCars(String makePattern,
Set<Security> requiredSecuirtySet)
{
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Car> query = builder.createQuery(Car.class);
Root<Car> car = query.from(Car.class);
query.select(car).where(
builder.equal(car.get("make"), makePattern),
car.get("securityList").in(requiredSecuirtySet));
return em.createQuery(query).getResultList();
}