Je veux utiliser des critères pour faire la requête suivante. J'ai un Entity with EmbeddedId défini:
@Entity
@Table(name="TB_INTERFASES")
public class Interfase implements Serializable {
@EmbeddedId
private InterfaseId id;
}
@Embeddable
public class InterfaseId implements Serializable {
@Column(name="CLASE")
private String clase;
}
Et la requête de critères que j'essaie de faire est la suivante:
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Interfase> criteriaQuery = criteriaBuilder.createQuery(Interfase.class);
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("clase"), "Clase"),
);
Mais cela jette une exception IllegalArgumentException:
Java.lang.IllegalArgumentException: Not an managed type: class InterfaseId
j'ai aussi essayé avec ces requêtes:
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),
);
et celui-ci aussi ...
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("id.clase", "Clase"),
);
ma question est la suivante: comment puis-je effectuer une requête avec des critères lorsque mes classes utilisent des annotations Embedded et EmbeddedId?
Merci! Mauro.
Vous devez utiliser la navigation par chemin pour accéder aux attributs de la variable Embeddable
. Voici un exemple tiré de la spécification JPA 2.0 (utilisant le métamodèle statique):
6.5.5 Navigation dans les chemins
...
Dans l'exemple suivant,
ContactInfo
est une classe incorporable Consistant en une adresse et un ensemble de Téléphones.Phone
est une entité.CriteriaQuery<Vendor> q = cb.createQuery(Vendor.class); Root<Employee> emp = q.from(Employee.class); Join<ContactInfo, Phone> phone = emp.join(Employee_.contactInfo).join(ContactInfo_.phones); q.where(cb.equal(emp.get(Employee_.contactInfo) .get(ContactInfo_.address) .get(Address_.zipcode), "95054")) .select(phone.get(Phone_.vendor));
La requête de langage Java Suivante est équivalente:
SELECT p.vendor FROM Employee e JOIN e.contactInfo.phones p WHERE e.contactInfo.address.zipcode = '95054'
Donc dans votre cas, je pense que vous aurez besoin de quelque chose comme ça:
criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")
Mise à jour: J'ai testé les entités fournies avec Hibernate EntityManager 3.5.6 et la requête suivante:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Interfase> criteria = builder.createQuery(Interfase.class);
Root<Interfase> interfaseRoot = criteria.from(Interfase.class);
criteria.select(interfaseRoot);
criteria.where(builder.equal(interfaseRoot.get("id").get("clase"),
"Referencia 111"));
List<Interfase> interfases = em.createQuery(criteria).getResultList();
fonctionne correctement et génère le code SQL suivant:
17: 20: 26.893 [main] DEBUG org.hibernate.SQL - Sélectionnez Interfase0_.CLASE comme CLASE31_ Parmi TB_INTERFASES interfase0_ .____.] où interfase0_.CLASE =? 17: 20: 26.895 [main] TRACE org.hibernate.type.StringType - liant «Référence 111» au paramètre: 1
Fonctionne comme prévu.
Essayez de copier et de coller les classes metamodel
dans le même dossier que celui dans lequel vos entités sont enregistrées (dans NetBeans 8.2, elles sont générées automatiquement et portent le même nom de votre entité, mais avec un trait de soulignement à la fin. Cela devrait ressembler à Interfase_
et InterfaseId_
).
Forcer l’importation des metamodel
classes Interfase_
et InterfaseId_
et faire référence au champ souhaité.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Interfase> criteria = builder.createQuery(Interfase.class);
Root<Interfase> interfaseRoot = criteria.from(Interfase.class);
criteria.select(interfaseRoot);
criteria.where(builder.equal(interfaseRoot.get(Interfase_.id).get(InterfaseId_.clase),"Referencia 111"));
List<Interfase> interfases = em.createQuery(criteria).getResultList();
C'est une vieille question, mais de toute façon ...
Une autre solution extrêmement simple est
InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);
Sauf si vous essayez de faire autre chose que ce que vous avez demandé, c'est la façon "saine" de le faire. Une requête sur l'id retournera au maximum un résultat.