I want to use criteria to make the following query. I have an Entity with EmbeddedId defined:
@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;
}
And the criteria query that i am trying to do is:
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"),
);
But this is throwing an IllegalArgumentException:
java.lang.IllegalArgumentException: Not an managed type: class InterfaseId
i've tried with this queries too:
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),
);
and this one too...
Root<Interfase> entity = criteriaQuery.from(Interfase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get("id.clase", "Clase"),
);
with no luck.
So my question is how can i make a query with criteria when my classes are using Embedded and EmbeddedId annotations?
Thanks!.
Mauro.
You need to use path navigation to access the attribute(s) of the Embeddable
. Here is an example from the JPA 2.0 specification (using the static metamodel):
6.5.5 Path Navigation
...
In the following example,
ContactInfo
is an embeddable class
consisting of an address and set of
phones. Phone
is an entity.
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));
The following Java Persistence query
language query is equivalent:
SELECT p.vendor
FROM Employee e JOIN e.contactInfo.phones p
WHERE e.contactInfo.address.zipcode = '95054'
So in your case, I think you'll need something like this:
criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")
References
- JPA 2.0 Specification
- Section 6.5.5 "Path Navigation"
Update: I've tested the provided entities with Hibernate EntityManager 3.5.6 and the following query:
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();
runs fine and generates the following 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
Works as expected.
It is an old question, but anyway...
Another extremely simple solution is
InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);
Except if you trying to do something else besides what you asked, this is the "sane" way to do it. A query on the id will return maximum one result.
Try to copy and paste the metamodel
classes into the same folder where your entities are saved (in NetBeans 8.2 they are automatically generated and have the same name of your entity but with an underscore at the end. Should be something like Interfase_
and InterfaseId_
).
Force the import of the metamodel
classes Interfase_
and InterfaseId_
and refer to the desired field.
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();