我想使用条件进行以下查询。我有实体, 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;
}
我想要做的标准查询是:
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"),
);
但是这会抛出IllegalArgumentException:
java.lang.IllegalArgumentException: Not an managed type: class InterfaseId
我也试过这个问题:
Root<Interfase> entity = criteriaQuery.from(Interfase.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"),
);
没有运气。
所以我的问题是,当我的类使用Embedded和EmbeddedId注释时,如何使用条件进行查询?
谢谢! 莫罗。
答案 0 :(得分:57)
您需要使用路径导航来访问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));
以下Java Persistence查询 语言查询是等价的:
SELECT p.vendor FROM Employee e JOIN e.contactInfo.phones p WHERE e.contactInfo.address.zipcode = '95054'
所以在你的情况下,我认为你需要这样的东西:
criteriaBuilder.equal(entity.get("id").get("clase"), "Referencia 111")
更新:我已经使用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();
运行正常并生成以下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
按预期工作。
答案 1 :(得分:0)
这是一个老问题,但无论如何......
另一个非常简单的解决方案是
InterfaseId id = new InterfaseId();
id.setClase("Clase");
Interfase found = em.find(id);
除了你想要做的事情之外,除了你提出的要求之外,这是“理智”的方式。对id的查询将返回最多一个结果。
答案 2 :(得分:0)
尝试将metamodel
类复制并粘贴到保存实体的同一文件夹中(在NetBeans 8.2中,它们是自动生成的,并且具有相同的实体名称,但最后使用下划线。应该是类似于Interfase_
和InterfaseId_
)。
强制导入metamodel
类Interfase_
和InterfaseId_
并引用所需的字段。
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();