JPA-标准API和EmbeddedId

JPA-标准API和EmbeddedId,jpa,jpa-2.0,criteria-api,composite-id,Jpa,Jpa 2.0,Criteria Api,Composite Id,我想使用条件进行以下查询。我有一个定义了嵌入ID的实体: @Entity @Table(name="TB_INTERFASES") public class Interfase implements Serializable { @EmbeddedId private InterfaseId id; } @Embeddable public class InterfaseId implements Serializable { @Column(name="CLASE"

我想使用条件进行以下查询。我有一个定义了嵌入ID的实体

 @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;
 }
我要做的条件查询是:

 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"),
 );
我也尝试过这样的查询:

 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),
 );
Root实体=criteriaQuery.from(interbase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get(“id”).get(“clase”),“clase”),
);
还有这个

 Root<Interfase> entity = criteriaQuery.from(Interfase.class);
 criteriaQuery.where(
   criteriaBuilder.equal(entity.get("id.clase", "Clase"),
 );
Root实体=criteriaQuery.from(interbase.class);
criteriaQuery.where(
criteriaBuilder.equal(entity.get(“id.clase”,“clase”),
);
没有运气。 所以我的问题是,当我的类使用嵌入式和嵌入式ID注释时,如何使用条件进行查询

谢谢!。
Mauro.

您需要使用路径导航来访问可嵌入的
属性。以下是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));
所以在你的情况下,我认为你需要这样的东西:

criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")
工具书类
  • JPA2.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();
CriteriaBuilder=em.getCriteriaBuilder();
CriteriaQuery criteria=builder.createQuery(interbase.class);
Root interbase Root=标准.from(interbase.class);
条件。选择(interbaseroot);
其中(builder.equal(interfaseRoot.get(“id”).get(“clase”),
“参考文件111”);
List interfases=em.createQuery(criteria).getResultList();
运行正常并生成以下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 17:20:26.893[main]DEBUG org.hibernate.SQL- 选择 干涉0。按类别31 从…起 TB_干扰酶干扰酶0_ 哪里 干涉0_u2;u.CLASE=? 17:20:26.895[main]TRACE org.hibernate.type.StringType-将“referencea 111”绑定到参数:1
这是一个老问题,但无论如何

另一个非常简单的解决方案是

InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);

除非您尝试执行除要求之外的其他操作,否则这是一种“明智”的方法。对id的查询将返回最多一个结果。

尝试将
元模型
类复制并粘贴到保存实体的同一文件夹中(在NetBeans 8.2中,它们是自动生成的,与您的实体名称相同,但末尾带有下划线。应该类似于
interbase\u
interbaseid\u

强制导入
元模型
interbase\u
interbaseid\u
并参考所需字段

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();
CriteriaBuilder=em.getCriteriaBuilder();
CriteriaQuery criteria=builder.createQuery(interbase.class);
Root interbase Root=标准.from(interbase.class);
条件。选择(interbaseroot);
其中(builder.equal(interbaseroot.get(interbase.id).get(interbaseid.clase),“referenceia 111”);
List interfases=em.createQuery(criteria).getResultList();

Hi Pascal,我试过了,但运气不好。正如我在帖子中所说,当我做entity.get(“id”)时,我得到了一个IllegalArgumentException。有什么建议吗?@Mauro不,你在问题中没有这样说。你在使用什么JPA实现?@Pascal,再次感谢你的回答…我使用的是Hibernate版本3.5.0-Beta2。例外情况是,InterbaseID是一个非托管实体。特别是IllegalArgumentException:不是托管类型:阶级InterfaseId@Mauro我的观点是,在您编写的问题中,您没有尝试过
entity.get(“id”)
,读者必须猜测您尝试了什么,这并不好。无论如何,我将用另一个实现尝试您的映射。@Pascal很抱歉误解。我已经编辑了这个问题,所以我希望这次能更清楚地说明我尝试了什么。我将尝试使用最新版本的Hibernate(3.6)或者Eclipse链接,我将返回结果,顺便说一句……我认为这是一个基本查询(浏览复合属性-在本例中为Embeeded类),所以hibernate很少不支持这种类型的查询。谢谢!。
InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);
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();