Java 用于搜索嵌套对象的规范/谓词

Java 用于搜索嵌套对象的规范/谓词,java,jpa,spring-data,specifications,predicate,Java,Jpa,Spring Data,Specifications,Predicate,我正在使用SpringBoot和SpringJPA以及规范执行器。我的规范/谓词组合成功地搜索了类中的简单属性。但是,我在搜索内部对象时遇到困难。他们需要单独的规格吗?我有一个类,其中包含2个多对一映射类,并且希望从同一个类中搜索这些字段 谓词实现 public Specification<User> getSpecification(SpecificationField field, Object searchCriteria){ return new Specificat

我正在使用SpringBoot和SpringJPA以及规范执行器。我的规范/谓词组合成功地搜索了类中的简单属性。但是,我在搜索内部对象时遇到困难。他们需要单独的规格吗?我有一个类,其中包含2个多对一映射类,并且希望从同一个类中搜索这些字段

谓词实现

public Specification<User> getSpecification(SpecificationField field, Object searchCriteria){
    return new Specification<User>() {
    @Override
    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

    if(searchCriteria instanceof String){
        searchCriteria.toString().trim().toLowerCase();
    }

    switch(field){
    case USER_GROUP:    
        return cb.equal(cb.lower(root.<String> get("group").get("name")), searchCriteria);
    case USER_ROLE: 
        return cb.equal(cb.lower(root.<String> get("role").get("name")), searchCriteria);
    case USER_EMAIL: 
        return cb.equal(cb.lower(root.<String> get("email")), searchCriteria);
    case USER_FIRSTNAME: 
        return cb.equal(cb.lower(root.<String> get("firstName")), searchCriteria);
    case USER_LASTNAME: 
        return cb.equal(cb.lower(root.<String> get("lastName")), searchCriteria);
    case USER_USERNAME: 
        return cb.equal(cb.lower(root.<String> get("username")), searchCriteria);
    default:
        assert true;
        return null;
    }

角色类

@Id
@GeneratedValue
@Column(name = "ROLE_ID")
private Long id;

@Column(name = "ROLE_NAME", nullable = false, unique = true)
private String name;

小组课

@Id
@GeneratedValue
@Column(name = "GROUP_ID")
private Long id;

@Column(name = "GROUP_NAME", nullable = false, unique = true)
private String name;

@Column(name = "GROUP_TOKEN", nullable = false, unique = true)
private String token;
-------------------------------------------------------------------------- 编辑:

提出了嵌套对象的谓词实现

Root<Group> group = query.from(Group.class);
Root<Role> role = query.from(Role.class);

switch(field){
case USER_GROUP:
    return cb.equal(cb.lower(group.<String> get("name")), searchCriteria);
case USER_ROLE: 
    return cb.equal(cb.lower(role.<String> get("name")), searchCriteria);
Root group=query.from(group.class);
根角色=query.from(role.class);
开关(现场){
案例用户组:
返回cb.equal(cb.lower(group.get(“name”)),searchCriteria);
案例用户角色:
返回cb.equal(cb.lower(role.get(“name”)),searchCriteria);
这工作得更好,但不是很好。我有可能的组名值DEV、UAT或PROD。如果我给出其中任何一个值,我会得到数据库中的所有用户。如果我不给出,我不会得到任何用户。我如何对这个嵌套对象的名称进行文本搜索


谢谢。

我自己找到了答案,但我想与大家分享,这样可以帮助其他人解决同样的问题

@Override
public Predicate toPredicate(Root<User> userRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {

    switch(field){
    case USER_GROUP:
        Join<User, Group> groupJoin = userRoot.join("group");
        return cb.equal(cb.lower(groupJoin.<String> get("name")), searchCriteria);
    case USER_ROLE: 
        Join<User, Role> roleJoin = userRoot.join("role");
        return cb.equal(cb.lower(roleJoin.<String> get("name")), searchCriteria);
@覆盖
公共谓词toPredicate(Root用户Root、CriteriaQuery查询、CriteriaBuilder cb){
开关(现场){
案例用户组:
Join-groupJoin=userRoot.Join(“组”);
返回cb.equal(cb.lower(groupJoin.get(“name”)),searchCriteria);
案例用户角色:
Join-roleJoin=userRoot.Join(“角色”);
返回cb.equal(cb.lower(roleJoin.get(“name”)),searchCriteria);

使用javax.persistence库中的Join类,我可以用相同的规范搜索类中的嵌套对象。

我们可以用一种更通用的方法将其应用于所有实体吗?JPA规范只允许您使用根目录中具有Hibernate映射的元素进行连接(据我所知)。这些是ManyToOne ManyToMany或OneToMany注释。你是说我必须为我拥有的每个实体创建一个单独的标准生成器,为所有实体创建一个独立的标准生成器?只有需要高级搜索的实体。JPA动态查询可用于最简单的搜索。如果我的内部对象说这个问题的角色是数据(注释)而不是实体(注释),那么?
@Override
public Predicate toPredicate(Root<User> userRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {

    switch(field){
    case USER_GROUP:
        Join<User, Group> groupJoin = userRoot.join("group");
        return cb.equal(cb.lower(groupJoin.<String> get("name")), searchCriteria);
    case USER_ROLE: 
        Join<User, Role> roleJoin = userRoot.join("role");
        return cb.equal(cb.lower(roleJoin.<String> get("name")), searchCriteria);