Category Hierarchy

我有两张表:

@Table(name = "userinstance")
@Entity
public class UserInstance implements Comparable<UserInstance> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(min = 1, max = 100)
    @Column(length = 100, unique = false, nullable = false)
    private String uuid;

    @NotNull
    @Size(min = 1, max = 100)
    @Column(length = 100, unique = false, nullable = false)
    String userId;

    @NotNull
    @Size(min = 1, max = 100)
    @Column(length = 100, unique = false, nullable = false)
    private String name;

    @NotNull
    @Size(min = 1, max = 2048)
    @Column(length = 2048, unique = false, nullable = false)
    private String description;

    @JsonBackReference
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "userInstance")
    private List<UserDetailsInstance> userDetailsInstances = new ArrayList<>();

}
@Table(name = "userdetailsinstance")
@Entity
public class UserDetailsInstance implements Comparable<UserDetailsInstance> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(min = 1, max = 100)
    @Column(length = 100, unique = false, nullable = false)
    private String uuid;

    @JsonManagedReference
    @ManyToOne
    @JoinColumn(name = "usr_instance_id", nullable = false)
    private UserInstance userinstance;

    @NotNull
    @Size(min = 1, max = 100)
    @Column(length = 100, unique = false, nullable = false)
    private String name;

    @NotNull
    @Size(min = 1, max = 100)
    @Column(length = 100, unique = false, nullable = false)
    private String type;

    @Column(length = 1)
    private Status status;

    @Column(length = 1000)
    private String message;

    @Column(length = 4000)
    private String instanceData;

}

我想要实现的是能够使用过滤器找到用户(UserInstance表),并且只使用一个查询参数("name");

为了做到这一点,我有一个:

public class UserInstanceQuery extends BaseQuery {

    private final Long id;

    private final String name;

    private final String user;

    private final Instant createdDate;

    private final Instant lastModifiedDate;

    public UserInstanceQuery(Long id, String name, String user, String createdDate, String lastModifiedDate, Pageable pageable) {
        super(pageable);
        this.id = id;
        this.name = name;
        this.user = user;
        this.createdDate = convertStringToInstant(createdDate);
        this.lastModifiedDate = convertStringToInstant(lastModifiedDate);
    }
    
    public Specification<UserInstance> toSpecification() {
        return new UserSpecification(this);
    }
}

该规范如下所示:

public class UserInstanceSpecification implements Specification<UserInstance> {

    private final UserInstanceQuery userInstanceQuery;

    @Override
    public Predicate toPredicate(Root<UserInstance> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> predicates = new LinkedList<>();

        if (userInstanceQuery.getId() != null) {
            predicates
                .add(
                    cb.equal(root.get("id"),
                        userInstanceQuery.getId())
                );
        }

        if (userInstanceQuery.getUser() != null && !userInstanceQuery.getUser().isEmpty()) {
            predicates
                .add(cb.equal(
                    cb.lower(root.get("userId")), userInstanceQuery.getUser().toLowerCase()));
        }

        if (userInstanceQuery.getName() != null && !userInstanceQuery.getName().isEmpty()) {
            Subquery<UserInstance> subquery = query.subquery(UserInstance.class);
            Root<UserDetailsInstance> subRoot = subquery.from(UserDetailsInstance.class);
            List<Predicate> subPredicates = new ArrayList<>();
            subPredicates.add(cb.like(subRoot.get("instanceData"), "%" + userInstanceQuery.getName() + "%"));

            subquery.select(subRoot.get("userInstance")).where(subPredicates.toArray(new Predicate[predicates.size()]));

            predicates.add(
                cb.or(
                    cb.like(cb.lower(root.get("name")), "%" + userInstanceQuery.getName().toLowerCase() + "%"),
                    cb.like(cb.lower(root.get("environment")), "%" + userInstanceQuery.getName().toLowerCase() + "%"),
                    cb.like(cb.lower(root.get("description")), "%" + userInstanceQuery.getName().toLowerCase() + "%"),
                    cb.exists(subquery)
                )
            );
        }

        if (userInstanceQuery.getCreatedDate() != null && userInstanceQuery.getLastModifiedDate() != null) {
            predicates.add(
                cb.and(
                    cb.greaterThanOrEqualTo(root.get("createdDate"), userInstanceQuery.getCreatedDate()),
                    cb.lessThanOrEqualTo(root.get("lastModifiedDate"), userInstanceQuery.getLastModifiedDate())
                )
            );
        }

        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }

    private boolean currentQueryIsCountRecords(CriteriaQuery<?> criteriaQuery) {
        return criteriaQuery.getResultType() == Long.class || criteriaQuery.getResultType() == long.class;
    }
}

问题是,当我搜索一个仅包含在UserDetailsInstance "instanceData“字段中的字符串时,我得到了多个结果,这些结果实际上没有我需要的数据,也没有引用用户

Hibernate生成的sql如下所示:

select user0_.id as id1_7_, user0_.created_by as created_by2_7_, user0_.created_date as created_date3_7_, user0_.last_modified_by as last_modified_by4_7_, user0_.last_modified_date as last_modified_date5_7_, user0_.version as version6_7_, user0_.description as description7_7_, user0_.environment as environment8_7_, user0_.name as name9_7_, user0_.user_id as user_id10_7_, user0_.uuid as uuid11_7_ from usertinstance user0_ 
where (lower(user0_.name) like ?
 or lower(user0_.environment) like ? 
 or lower(user0_.description) like ? 
 or exists (select userdetail.tds_instance_id 
      from userdetailsinstance userdetail 
      cross join usertinstance user2_ 
          where userdetail.tds_instance_id=user2_.id 
      and (userdetail.instance_data like ?))) 
  and user0_.created_date>=? and user0_.last_modified_date<=? order by user0_.id desc fetch first ? rows only

如果我尝试在SQLDeveloper/Datagrip中运行此查询,如果我进行更改,也会同时得到多组行(第8行)

where userdetail.usr_instance_id=user2_.id 

where userdetail.usr_instance_id=user0_.id 

我得到了我需要的结果

您能告诉我创建查询时出现的错误吗?或者告诉我如何使此查询返回所需的值

谢谢!

转载请注明出处:http://www.biaocun.net/article/20230526/2071495.html