Если у меня есть два класса - "Грузовик и оборудование" - с отношением "многие ко многим", я хотел бы написать JPA CriteriaQuery, чтобы найти все Грузовики, которые соответствуют определенному идентификатору оборудования. Для простоты эти два класса заключаются в следующем. Грузовик имеет список оборудования, но оборудование не знает о грузовике:
public class Truck {
private Long id;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(
name="truck_equipment",
joinColumns={ @JoinColumn(name="truck_id") },
inverseJoinColumns={ @JoinColumn(name="equip_id") }
)
private List<Equipment> equipment;
}
public class Equipment {
private Long id;
private String equipCode;
}
Я знаю, что могу написать запрос на получение всего Оборудования для определенного грузовика, но мне бы хотелось наоборот: все грузовики с определенным оборудованием, и я просто не могу получить то, что я ищу. Вот обратный запрос, который дает мне все оборудование для определенного грузовика:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Equipment> cq = cb.createQuery(Equipment.class);
Root<Truck> truckRoot = cq.from(Truck.class);
cq.where(cb.equal(truckRoot.get(Truck_.id), truckId));
ListJoin<Truck, Equipment> trucks = truckRoot.join(Truck_.equipment);
CriteriaQuery<Equipment> cq_e = cq.select(trucks);
TypedQuery<Equipment> query = entityManager.createQuery(cq_e);
query.getResultList();
Может ли кто-нибудь помочь мне получить обратный запрос?
Мы закончили тем, что сделали следующее. Я не уверен, что он так же эффективен, как и любой другой способ, но он по-прежнему позволяет нам сохранить классы метамодели, которые были важны для нас, и сохранить ссылку на объект с одной стороны, чтобы избежать проблемы при записи этих объектов в JSON (бесконечный рекурсия):
private getEquipmentPredicate(CriteriaBuilder cb, Root<Truck> root) {
EquipmentType type = findEquipmentType("not related to this answer");
Expression<List<EquipmentType>> equipments = root.get(Truck_.equipmentTypes);
Predicate p = cb.isMember(type, equipments);
return p;
}
Я сделал трюк с:
String someCode = "xxx";
CriteriaBuilder builder = ...
builder.and(
root.join(Truck_.equipmentTypes).get(Equipment_.equipCode)
.in(Collections.singleton(someCode)
);