primary - JPA-Criteria API y EmbeddedId
jpa composite primary key (3)
Quiero usar criterios para hacer la siguiente consulta. Tengo una Entidad con EmbeddedId definido:
@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;
}
Y la consulta de criterios que estoy tratando de hacer es:
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"),
);
Pero esto arroja una excepción IllegalArgumentException:
java.lang.IllegalArgumentException: Not an managed type: class InterfaseId
Lo intenté con estas consultas también:
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),
);
y ésta también...
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("id.clase", "Clase"),
);
sin suerte Entonces mi pregunta es ¿cómo puedo hacer una consulta con criterios cuando mis clases usan anotaciones incrustadas e incrustadas?
¡Gracias!. Mauro.
Es una vieja pregunta, pero de todos modos ...
Otra solución extremadamente simple es
InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);
Excepto si intentas hacer algo más además de lo que preguntaste, esta es la manera "sensata" de hacerlo. Una consulta en el id devolverá un resultado máximo.
Intenta copiar y pegar las clases del metamodel
en la misma carpeta donde se guardan tus entidades (en NetBeans 8.2 se generan automáticamente y tienen el mismo nombre de tu entidad pero con un guión bajo al final. Debería ser algo como Interfase_
e InterfaseId_
).
Fuerce la importación de las clases metamodel
Interfase_
e InterfaseId_
y consulte el campo deseado.
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();
Necesita usar la navegación de ruta para acceder a los atributos de Embeddable
. Aquí hay un ejemplo de la especificación JPA 2.0 (usando el metamodelo estático):
6.5.5 Navegación de ruta
...
En el siguiente ejemplo,
ContactInfo
es una clase incrustable que consiste en una dirección y un conjunto de teléfonos.Phone
es una entidad.
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 siguiente consulta de lenguaje de consulta de Java Persistence es equivalente:
SELECT p.vendor FROM Employee e JOIN e.contactInfo.phones p WHERE e.contactInfo.address.zipcode = ''95054''
Entonces, en tu caso, creo que necesitarás algo como esto:
criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")
Referencias
- Especificación JPA 2.0
- Sección 6.5.5 "Navegación de ruta"
Actualización: He probado las entidades proporcionadas con Hibernate EntityManager 3.5.6 y la siguiente consulta:
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();
funciona bien y genera el siguiente SQL:
17:20:26.893 [main] DEBUG org.hibernate.SQL - select interfase0_.CLASE as CLASE31_ from TB_INTERFASES interfase0_ where interfase0_.CLASE=? 17:20:26.895 [main] TRACE org.hibernate.type.StringType - binding ''Referencia 111'' to parameter: 1
Funciona como se esperaba