我有两张表:
@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