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!
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 autrejoin
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 etY
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
- de la section 6.2.1 Statique de la Méta-modèle des Classes dans la JPA 2.0
- Dynamique, typesafe requêtes en JPA 2.0
- utilisation des critères API et API Metamodel pour créer des requêtes de base de Type
question connexe
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));
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);
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.