Подтвердить что ты не робот

API-интерфейс JPA - Как добавить предложение JOIN (как можно более общее предложение)

Я пытаюсь построить запросы динамически, и моя следующая цель - добавить предложения JOIN (я не знаю, как я могу использовать API).

В настоящее время, например, этот код работает для меня:

...
Class baseClass;   
...
CriteriaBuilder cb = JpaHandle.get().getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(this.baseClass);
Root entity_ = cq.from(this.baseClass); 
Predicate restrictions = null;
...
restrictions = cb.conjunction();
restrictions = cb.and(restrictions, entity_.get("id").in(this.listId));
...
cq.where(restrictions);
...
Query qry = JpaHandle.get().createQuery(cq);

(Примечание: JpaHandle - из реализации калитки-JPA)

Мое желание - добавить предложение JOIN (как можно больше)!

У меня есть специальные аннотации в классах (this.baseClass)

Например:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assay_id", nullable = false)

Итак, Есть ли способ сделать что-то подобное в стандартной JPA? (Примечание: это не компилируется)

Здесь практическая ошибка aproaches:

...
Join<Experiment,Assay> experimentAssays = entity_.join( entity_.get("assay_id") );

Или так:

...
CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
Root<Customer> c = q.from(Customer.class);
SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders);

Для меня, если бы это было возможно более общее, это будет здорово...:

...
Join joinClause = entity_join(entity_.get("assay_id"), entity2_.get("id"));

Конечно, у меня есть специальные аннотации в классах (this.baseClass)

Спасибо за ваше время. Я буду благодарен за все комментарии!

4b9b3361

Ответ 1

Может быть, следующая выдержка из главы 23 - Использование Criteria API для создания запросов руководства по Java EE 6 проливает некоторый свет (на самом деле, я предлагаю прочитать всю главу 23):

Запрос отношений с помощью соединений

Для запросов, которые переходят к связанным классам сущностей, запрос должен определить соединение со связанной сущностью, вызвав один из методов From.join для корневого объекта запроса или другой объект join. Методы объединения аналогичны ключевому слову JOIN в JPQL.

Цель объединения использует класс Metamodel типа EntityType<T> чтобы указать постоянное поле или свойство присоединяемой сущности.

Методы объединения возвращают объект типа Join<X, Y>, где X - исходная сущность, а Y - цель объединения.

Пример 23-10 Присоединение к запросу

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(Pet_.owners);

Объединения могут быть объединены в цепочку для перехода к связанным объектам целевого объекта без необходимости создавать экземпляр Join<X, Y> для каждого объединения.

Пример 23-11. Объединение цепочек в запрос

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);
EntityType<Owner> Owner_ = m.entity(Owner.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Owner, Address> address = cq.join(Pet_.owners).join(Owner_.addresses);

При этом у меня есть несколько дополнительных замечаний:

Во-первых, следующая строка в вашем коде:

Root entity_ = cq.from(this.baseClass);

Заставляет меня думать, что вы как-то пропустили часть Статических Метамодельных Классов. Классы метамодели, такие как Pet_ в приведенном примере, используются для описания метаинформации постоянного класса. Они обычно генерируются с использованием процессора аннотаций (классы канонической метамодели) или могут быть написаны разработчиком (неканоническая метамодель). Но ваш синтаксис выглядит странно, я думаю, вы пытаетесь имитировать то, что вы пропустили.

Во-вторых, я действительно думаю, что вы должны забыть этот внешний ключ assay_id, вы здесь не на том пути. Вам действительно нужно начать думать об объекте и ассоциации, а не о таблицах и столбцах.

В-третьих, я не совсем понимаю, что именно вы имеете в виду, добавив как можно более общее предложение JOIN и то, как выглядит ваша объектная модель, поскольку вы ее не предоставили (см. Предыдущий пункт). Таким образом, просто невозможно ответить на ваш вопрос более точно.

Подводя итог, я думаю, что вам нужно прочитать немного больше о JPA 2.0 Criteria и Metamodel API, и я настоятельно рекомендую нижеприведенные ресурсы в качестве отправной точки.

Смотрите также

Связанный вопрос

Ответ 2

На самом деле вам не нужно иметь дело со статической метамоделью, если вы правильно сделали свои аннотации.

Со следующими лицами:

@Entity
public class Pet {
  @Id
  protected Long id;
  protected String name;
  protected String color;
  @ManyToOne
  protected Set<Owner> owners;
}

@Entity
public class Owner {
  @Id
  protected Long id;
  protected String name;
}

Вы можете использовать это:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> petMetaModel = m.entity(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(petMetaModel.getSet("owners", Owner.class));

Ответ 3

Вам не нужно изучать JPA. Вы можете использовать мои простые критерии для JPA2 (https://sourceforge.net/projects/easy-criteria/files/). Вот пример

CriteriaComposer<Pet> petCriteria CriteriaComposer.from(Pet.class).
where(Pet_.type, EQUAL, "Cat").join(Pet_.owner).where(Ower_.name,EQUAL, "foo");

List<Pet> result = CriteriaProcessor.findAllEntiry(petCriteria);

ИЛИ

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);

Ответ 4

Внимание! Там содержится ряд ошибок в примере Sun JPA 2 и в результате вставленного содержимого в Pascal. Пожалуйста, обратитесь к этому сообщению.

Этот пост и пример Sun Java EE 6 JPA 2 действительно сдерживали мое понимание JPA 2. После вспашки в руководствах Hibernate и OpenJPA и размышления о том, что я хорошо разбираюсь в JPA 2, я все равно запутался после возвращения к этому сообщению.