Использование JPA Criteria Query API для примера «многие ко многим»

1

Если у меня есть два класса - "Грузовик и оборудование" - с отношением "многие ко многим", я хотел бы написать 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();

Может ли кто-нибудь помочь мне получить обратный запрос?

  • 0
    Для этого вам нужны обе стороны набора ассоциаций. Таким образом, оборудование также будет иметь ссылку на грузовики, которые вы можете использовать при запросах. Это также хорошее время, чтобы решить, является ли это ассоциацией «многие ко многим» или «один ко многим».
  • 0
    Да, это просто сделать, если у обеих сторон есть ссылка. Мы удалили ссылку с одной стороны из-за проблем при записи объектов в JSON - проблема бесконечной рекурсии.
Теги:
hibernate
jpa
criteria-api

2 ответа

0
Лучший ответ

Мы закончили тем, что сделали следующее. Я не уверен, что он так же эффективен, как и любой другой способ, но он по-прежнему позволяет нам сохранить классы метамодели, которые были важны для нас, и сохранить ссылку на объект с одной стороны, чтобы избежать проблемы при записи этих объектов в 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;
}
0

Я сделал трюк с:

String someCode = "xxx";
CriteriaBuilder builder = ...
builder.and(
        root.join(Truck_.equipmentTypes).get(Equipment_.equipCode)
                        .in(Collections.singleton(someCode)
);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню