嵌套集的 JPA 条件查询
JPA Criteria query for a nested set
我在该实体中有一个 Person 实体我有一组嵌套的 PersonNames 实体。 Person 和 PersonNames 之间存在 OneToMany 关系,一个人可以有多个名字。
@XmlElementWrapper(name = "names")
@XmlElement(name = "name")
@OneToMany(mappedBy = "person", orphanRemoval = false, fetch = FetchType.EAGER)
private Set<PersonNames> name;
您可以看到上面是如何定义 PersonNames 集的。
我需要创建一个 JPA 条件查询来查找所有具有与 firstName、middleName 或 lastName 匹配的 PersonNames 对象的 Person 实体。
public List<Person> getPerson(String lastName, String middleName, String firstName) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
criteria.select(root);
if(!lastName.isEmpty() && lastName != null) {
Predicate lastNameCondition = builder.equal( root.get(Person_.personId).get(PersonNames_.lastName), lastName);
criteria.where(lastNameCondition);
}
TypedQuery<Person> query = em.createQuery(criteria);
return query.getResultList();
}
以上是我完成上述查询的尝试,但是我在 Predicate 行的“.get(Person_.personId)”部分收到以下错误:
类型 Path 中的方法 get(SingularAttribute) 不适用于参数 (SingularAttribute)
谓词行可能完全错误,但我想不出如何做到这一点,我 google 似乎没有任何结果。我需要为此进行显式连接吗?
编辑:删除了 Hibernate 标签,因为我意识到它是我们的 Wildfly 服务器想要使用的,但我们没有在我们的代码中使用 Hibernate。
这行得通吗?
Criteria c = s.createCriteria(Person.class);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.createAlias("name", "name");
c.add(Restrictions.eq("name.lastName", lastName));
return c.list();
回复:"not using Hibernate API in our code" -- 它正在被弃用。
CriteriaApi 有一些批评者,但无论如何,一旦掌握了要领,就可以很容易地使用它。
@Entity
public class Person {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy="person")
private Set<PersonName> names;
并填充它:
tx.begin();
Person p = new Person();
PersonName c1 = new PersonName(p, "F1", "M1", "L1");
PersonName c2 = new PersonName(p, "F2", "M2", "L2");
em.persist(p);
em.persist(c1);
em.persist(c2);
tx.commit();
并查询它
em.clear();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> person = query.from(Person.class);
Join<Person, PersonName> names = person.join("names");
Predicate[] findNames = new Predicate[3];
findNames[0] = cb.equal(names.get("firstName"), "F1");
findNames[1] = cb.equal(names.get("middleName"), "M1");
findNames[2] = cb.equal(names.get("lastName"), "L1");
query.where(findNames);
List<Person> persons = em.createQuery(query).getResultList();
System.out.println(persons);
我在该实体中有一个 Person 实体我有一组嵌套的 PersonNames 实体。 Person 和 PersonNames 之间存在 OneToMany 关系,一个人可以有多个名字。
@XmlElementWrapper(name = "names")
@XmlElement(name = "name")
@OneToMany(mappedBy = "person", orphanRemoval = false, fetch = FetchType.EAGER)
private Set<PersonNames> name;
您可以看到上面是如何定义 PersonNames 集的。
我需要创建一个 JPA 条件查询来查找所有具有与 firstName、middleName 或 lastName 匹配的 PersonNames 对象的 Person 实体。
public List<Person> getPerson(String lastName, String middleName, String firstName) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
criteria.select(root);
if(!lastName.isEmpty() && lastName != null) {
Predicate lastNameCondition = builder.equal( root.get(Person_.personId).get(PersonNames_.lastName), lastName);
criteria.where(lastNameCondition);
}
TypedQuery<Person> query = em.createQuery(criteria);
return query.getResultList();
}
以上是我完成上述查询的尝试,但是我在 Predicate 行的“.get(Person_.personId)”部分收到以下错误:
类型 Path 中的方法 get(SingularAttribute) 不适用于参数 (SingularAttribute)
谓词行可能完全错误,但我想不出如何做到这一点,我 google 似乎没有任何结果。我需要为此进行显式连接吗?
编辑:删除了 Hibernate 标签,因为我意识到它是我们的 Wildfly 服务器想要使用的,但我们没有在我们的代码中使用 Hibernate。
这行得通吗?
Criteria c = s.createCriteria(Person.class);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.createAlias("name", "name");
c.add(Restrictions.eq("name.lastName", lastName));
return c.list();
回复:"not using Hibernate API in our code" -- 它正在被弃用。
CriteriaApi 有一些批评者,但无论如何,一旦掌握了要领,就可以很容易地使用它。
@Entity
public class Person {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy="person")
private Set<PersonName> names;
并填充它:
tx.begin();
Person p = new Person();
PersonName c1 = new PersonName(p, "F1", "M1", "L1");
PersonName c2 = new PersonName(p, "F2", "M2", "L2");
em.persist(p);
em.persist(c1);
em.persist(c2);
tx.commit();
并查询它
em.clear();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> person = query.from(Person.class);
Join<Person, PersonName> names = person.join("names");
Predicate[] findNames = new Predicate[3];
findNames[0] = cb.equal(names.get("firstName"), "F1");
findNames[1] = cb.equal(names.get("middleName"), "M1");
findNames[2] = cb.equal(names.get("lastName"), "L1");
query.where(findNames);
List<Person> persons = em.createQuery(query).getResultList();
System.out.println(persons);