我有一个实体(人),它是另一个实体(用户)的一对一。我需要使用CriteriaQuery查找与User.name匹配的所有Person实体。

我可以对Person的直接属性做简单的CriteriaQuery:

builder.like(builder.lower(root.get(column)), "%" + pattern.toLowerCase() + "%")


在这种更复杂的情况下,我对如何执行CriteriaQuery查询有些迷惑。从我在这里和其他地方的搜索,我认为我必须使用某种Join,但我无法为之困惑。

@Entity()
public class Person extends ModelCore {
    @Basic()
    private String iD = null;
    @OneToOne(cascade = { CascadeType.ALL })
    @JoinColumns({ @JoinColumn(name = "T_User") })
    private User user = null;
}

@Entity()
public class User extends ModelCore {
    @Basic()
    private String iD = null;
    @Basic()
    private String name = null;
}

@Entity()
public class ModelCore{
    @Basic()
    private Long dbID = null;
}


解决了

Nikos的解决方案效果很好(谢谢!):

String username = ... // the criterion
EntityManager em = ...
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> query = cb.createQuery(Person.class);
Root<Person> root = query.from(Person.class);
Join<Person, User> joinUser = root.join("user");
query.where(cb.like(cb.lower(joinUser.get("name")), "%" + username.toLowerCase() + "%"));


编辑1:添加了ModelCore作为基类。
编辑2:添加工作解决方案

最佳答案

随着复杂性的增加,标准API可能会造成混乱。我始终遵循的第一步是写下JPQL查询。在这种情况下:

SELECT p
FROM Person p
  JOIN User u
WHERE LOWER(u.name) LIKE :username


将此转换为Criteria API是:

// These are initializations
String username = ... // the criterion
EntityManager em = ...
CriteriaBuilder cb = em.getCriteriaBuilder();
// Next line means "the result of the query is Person"
CriteriaQuery<Person> query = cb.createQuery(Person.class);
// This matches the "FROM Person p" part of the JPQL
Root<Person> root = query.from(Person.class);
// This matches the "JOIN User u" part of the JPQL
Join<Person, User> joinUser = root.join("user"); // if you have created the metamodel, adjust accordingly
// This is the "WHERE..." part
query.where(cb.like(cb.lower(joinUser.get("name")), "%" + username.toLowerCase() + "%"));


WHERE部分令人困惑,因为您必须将中缀SQL / JPQL运算符转换为前缀(即x LIKE y变为cb.like(x, y)),但是映射很简单。

10-05 22:07