JPA - 标准 API 和 EmbeddedId [英] JPA - Criteria API and EmbeddedId

查看:32
本文介绍了JPA - 标准 API 和 EmbeddedId的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 @Entity@Table(name="TB_INTERFASES")公共类接口实现可序列化{@EmbeddedId私有InterfaseId id;}@Embeddable公共类 InterfaseId 实现了 Serializable {@Column(名称=CLASE")私有字符串类;}

我想做的标准查询是:

 CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();CriteriaQuery标准查询 = 标准构建器.createQuery(Interfase.class);根<接口>entity = criteriaQuery.from(Interfase.class);条件查询.where(criteriaBuilder.equal(entity.get("class"), "Clase"),);

但这会抛出一个 IllegalArgumentException:

java.lang.IllegalArgumentException:不是托管类型:类 InterfaseId

我也试过这个查询:

 Rootentity = criteriaQuery.from(Interfase.class);条件查询.where(criteriaBuilder.equal(entity.get("id").get("clase"), "Clase"),);

还有这个...

 Rootentity = criteriaQuery.from(Interfase.class);条件查询.where(criteriaBuilder.equal(entity.get("id.clase", "Clase"),);

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

谢谢!毛罗.

解决方案

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

<块引用>

6.5.5 路径导航

...

在下面的例子中,ContactInfo 是一个可嵌入的类由一个地址和一组电话.Phone 是一个实体.

CriteriaQueryq = cb.createQuery(Vendor.class);根<员工>emp = q.from(Employee.class);加入电话 =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));

以下 Java 持久化查询语言查询等价:

SELECT p.vendorFROM Employee e JOIN e.contactInfo.phones pWHERE e.contactInfo.address.zipcode = '95054'

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

criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")

参考资料

  • JPA 2.0 规范
    • 第 6.5.5 节路径导航"
<小时>

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

CriteriaBuilder builder = em.getCriteriaBuilder();CriteriaQuery标准 = builder.createQuery(Interfase.class);根<接口>interfaseRoot = criteria.from(Interfase.class);标准.选择(interfaceRoot);标准.where(builder.equal(interfaseRoot.get("id").get("class"),"参考文献 111"));列表<接口>interfases = em.createQuery(criteria).getResultList();

运行良好并生成以下 SQL:

<前>17:20:26.893 [主] 调试 org.hibernate.SQL -选择interfase0_.CLASE 作为 CLASE31_从TB_INTERFASES 接口0_在哪里接口0_.CLASE=?17:20:26.895 [main] TRACE org.hibernate.type.StringType - 将Referencia 111"绑定到参数:1

按预期工作.

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.

这篇关于JPA - 标准 API 和 EmbeddedId的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆