Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
544 views
in Technique[技术] by (71.8m points)

jpa 2.0 - JPA - Criteria API and EmbeddedId

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...