JPA Criteria API - Как добавить предложение JOIN (как можно более общее предложение) - PullRequest
30 голосов
/ 06 августа 2010

Я пытаюсь создавать запросы динамически, и моя следующая цель - добавить предложения 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 из реализации wicket-JPA)

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

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

Например:

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

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

Вот практический провал:

...
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)

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

Ответы [ 4 ]

40 голосов
/ 07 августа 2010

Может быть, следующая выдержка из Глава 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 как можно более универсальным * 1055.* и как выглядит ваша объектная модель, поскольку вы ее не предоставили (см. предыдущий пункт).Таким образом, просто невозможно ответить на ваш вопрос более точно.

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

См. Также

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

13 голосов
/ 13 декабря 2012

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

Со следующими объектами:

@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));
5 голосов
/ 07 февраля 2013

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

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

5 голосов
/ 11 июня 2011

Вам не нужно изучать 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);

OR

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...