API critères JPA-comment ajouter une clause JOIN (phrase aussi générale que possible ) )

j'essaie de construire des requêtes de manière dynamique, et ma prochaine cible est d'ajouter des clauses de jointure (Je ne sais pas comment utiliser L'API).

maintenant, par exemple, ce code fonctionne pour moi :

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

(Note : JpaHandle est à partir de guichet implémentation JPA)

mon désir est d'ajouter une clause de jointure (aussi générale que possible)!

j'ai les annotations particulières dans les classes (ce.baseClass)

par exemple:

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

alors, y a-t-il un moyen de faire quelque chose comme ça dans le JPA standard ? (Note : Ceci ne compile pas)

ici un échec pratique aproches:

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

ou comme ça:

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

pour moi, si elle pouvait être plus générale que possible, elle serait grande... :

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

de bien sûr, j'ai les annotations particulières dans les classes (ceci.baseClass)

Merci pour votre temps. Je vais apprécier tous les types de commentaires!

27
demandé sur Pascal Thivent 2010-08-06 18:24:02

4 réponses

peut - être que l'extrait suivant du Chapitre 23-utilisation de L'API critères pour créer des requêtes du tutoriel Java EE 6 va jeter un peu de lumière (en fait, je suggère de lire l'ensemble du Chapitre 23):

Interroger Les Relations À L'Aide De Jointures

pour les requêtes qui naviguent les classes d'entity, la requête doit définir une adhésion à l'entité liée par appel une des méthodes From.join sur l'objet racine de la requête, ou un autre join objet. Les méthodes de jointure sont similaire au mot-clé JOIN dans JPQL.

La cible de la jointure utilise le Méta-modèle de la classe de type EntityType<T> pour préciser domaine persistant ou propriété de la rejoint entité.

les méthodes de jointure renvoient un objet de type Join<X, Y> , où X est le entité d'origine et Y est la cible de joint.

exemple 23-10 joindre une requête

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

peut être enchaîné ensemble à naviguer vers les entités liées de la entité cible sans avoir à créer une instance Join<X, Y> pour chaque jointure.

Exemple 23-11 L'Enchaînement S'Unit dans une requête

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

cela étant dit, j'ai quelques remarques supplémentaires:

D'abord, la ligne suivante dans votre code:

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

me fait penser que vous avez d'une façon ou d'une autre manqué la partie des Classes de métamodèle statique. Les classes de métamodèle telles que Pet_ dans l'exemple cité sont utilisées pour décrire la méta-information d'une classe persistante. Ils sont typiquement généré à l'aide d'un processeur d'annotation ( classes de métamodèle canonique ) ou peut être écrit par le développeur ( metamodel non canonique ). Mais votre syntaxe semble bizarre, je pense que vous essayez d'imiter quelque chose que vous avez manqué.

deuxièmement, je pense vraiment que vous devriez oublier cette assay_id clé étrangère, vous êtes sur le mauvais chemin ici. Vous devez vraiment commencer à penser objet et association, pas des tables et des colonnes.

Troisièmement, Je ne suis pas sûr de comprendre ce que vous voulez dire exactement en ajoutant une clause de jointure aussi générale que possible et à quoi ressemble votre modèle d'objet, puisque vous ne l'avez pas fourni (voir point précédent). C'est donc tout simplement impossible de répondre à votre question plus précisément.

pour résumer, je pense que vous avez besoin de lire un peu plus sur les critères JPA 2.0 et L'API Metamodel et je recommande vivement les ressources ci-dessous comme point de départ.

Voir aussi

question connexe

37
répondu Pascal Thivent 2017-05-23 12:25:43

en fait, vous n'avez pas à traiter avec le métamodèle statique si vous aviez vos annotations droite.

vous pouvez utiliser ceci:

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));
12
répondu Christophe Opoix 2012-12-13 09:41:29

vous n'avez pas besoin d'apprendre le JPA. Vous pouvez utiliser mes critères faciles pour JPA2 ( https://sourceforge.net/projects/easy-criteria/files / ). Voici l'exemple

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

ou

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);
6
répondu user793442 2016-10-18 15:35:05

Attention! Il y a un certain nombre d'erreurs dans L'exemple de Sun JPA 2 et le contenu collé qui en résulte dans la réponse de Pascal. Veuillez consulter ce post .

ce post et L'exemple Sun Java EE 6 JPA 2 ont vraiment entravé ma compréhension de JPA 2. Après avoir passé en revue les manuels D'hibernation et D'OpenJPA et avoir pensé que j'avais une bonne compréhension de JPA 2, je me suis encore embrouillé par la suite en revenant à ce poste.

5
répondu Chris Harris 2017-05-23 11:54:12