JPA - Criteria API和EmbeddedId

Mau*_*nti 27 jpa composite-id criteria-api jpa-2.0

我想使用条件来进行以下查询.我有一个实体EmbeddedId定义:

 @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;
 }
Run Code Online (Sandbox Code Playgroud)

我想要做的标准查询是:

 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"),
 );
Run Code Online (Sandbox Code Playgroud)

但是这会抛出IllegalArgumentException:

java.lang.IllegalArgumentException: Not an managed type: class InterfaseId
Run Code Online (Sandbox Code Playgroud)

我也尝试过这个问题:

 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),
 );
Run Code Online (Sandbox Code Playgroud)

而且这个......

 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("id.clase", "Clase"),
 );
Run Code Online (Sandbox Code Playgroud)

没有运气.所以我的问题是,当我的类使用Embedded和EmbeddedId注释时,如何使用条件进行查询?

谢谢!.毛罗.

Pas*_*ent 59

您需要使用路径导航来访问该属性Embeddable.以下是JPA 2.0规范中的一个示例(使用静态元模型):

6.5.5路径导航

...

在以下示例中, ContactInfo是一个可嵌入的类,包含一个地址和一组电话.Phone是一个实体.

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));
Run Code Online (Sandbox Code Playgroud)

以下Java Persistence查询语言查询是等效的:

SELECT p.vendor
FROM Employee e JOIN e.contactInfo.phones p
WHERE e.contactInfo.address.zipcode = '95054'
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,我认为你需要这样的东西:

criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")
Run Code Online (Sandbox Code Playgroud)

参考

  • JPA 2.0规范
    • 第6.5.5节"路径导航"

更新:我已经使用Hibernate EntityManager 3.5.6和以下查询测试了提供的实体:

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();
Run Code Online (Sandbox Code Playgroud)

运行正常并生成以下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

按预期工作.