如何使用 Criteria Builder 处理一对多关系中的空值。
我正在使用 API 中的条件生成器来获取结果。
我面临的问题是,当我传递
student_group
表中可用的任何文本时,我得到了结果。当我给出 null 时,我的 lastRollResult 在 student
表中为 null,我得到结果,但是当我传递文本和 null 的组合时,我没有得到结果。
我的API是这样的
http://localhost:8080/student?query=grade:5,lastRollResult%40SUCCESS%23FAILURE
在这种情况下我能够获取数据
http://localhost:8080/student?query=grade:5,lastRollResult%null
在这种情况下我无法获取数据
现在这是我正在尝试的以及我的代码的样子。
我的控制器。
控制器类:
@RequestMapping(method = RequestMethod.GET)
public Page<StudentDTO> index(MySpecificationsBuilder builder,
@PageableDefault(value = 25, page = 0) Pageable pageable) {
Specification<Student> spec = builder.build();
Page<Student> stu = studentService.findAll(spec, pageable);
/** here some modification on retuen */
}
您可以注意到在控制器中我正在构建 MySpecificationsBuilder,其中所有标准都已设置。这是关于 MySpecificationsBuilder 的简介
public class MySpecificationsBuilder extends BaseSpecification<Student> {
public MySpecificationsBuilder(final SearchCriteria criteria) {
super(criteria);
}
@Override
protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {
/** some other conditions */
if (criteria.getKey().equals("lastRollResult")) {
if (!"null".contains(criteria.getValue())) {
Join results = root.join("lastRoll", JoinType.INNER); // In case of text (JoinType.INNER is enum of Inner.
return results.get("result");
}else{
return root.get("lastRoll”); // in case of null
}
}
return root.get(criteria.getKey());
}
/** below toPredicate methods */
}
在 MySpecificationsBuilder 中,我正在做一些其他计算,如 resultConstant 和 toPredicate 结果。
在这里,正如您所看到的,在文本的情况下我正在执行内部连接,但在 null 的情况下我直接获取数据。这就是我收到此回复的原因。如何修复这个值。
这是我的桌子详细信息。
@Entity
@Data
@DiscriminatorFormula("case when entity_type is null then ‘Student’ else entity_type end")
@DiscriminatorValue("Student")
public class Student extends AbstractStudent {
@ManyToOne
@Fetch(value = FetchMode.SELECT)
@JoinColumn(name = "created_by_id", insertable = false, updatable = false)
@EqualsAndHashCode.Exclude
@ToString.Exclude
@NotFound(action = NotFoundAction.IGNORE)
User createdBy;
@Transient
private String name;
@Transient
private List<String> tags;
}
和抽象学生
@RequiresAudit
@Log4j2
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Data
@Entity
@Table(name = "student_group")
@DiscriminatorColumn(name = "entity_type", discriminatorType = DiscriminatorType.STRING)
public class AbstractStudent extends BaseModel {
@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
@EqualsAndHashCode.Exclude
@ToString.Exclude
List<StudentMapping> studentMappings;
@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
@EqualsAndHashCode.Exclude
@ToString.Exclude
List<StudentDataMapping> studentDataMapping;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@AuditColumn
@Column(name = "last_roll_id")
private Long lastRollId;
@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
@EqualsAndHashCode.student
@ToString.Exclude
private Set<TagUse> tagUses;
@ManyToOne
@Fetch(value = FetchMode.SELECT)
@JoinColumn(name = "last_roll_id", referencedColumnName = "id", insertable = false, updatable = false)
@EqualsAndHashCode.Exclude
@ToString.Exclude
@NotFound(action = NotFoundAction.IGNORE)
private Result lastRoll;
/** some other column defination */
}
在我的摘要栏中您可以进行一对一的映射。
是否有任何解决方案,例如组或任何 where 子句或任何其他东西,我可以通过这些解决方案将这两个参数组合在一起以获得 null 和文本的结果。
您可能需要修改 Criteria API 查询的构建方式。具体来说,您需要确保您的查询可以处理 lastRollResult 字段的空值和非空值。
// MySpecificationsBuilder
@Override
protected Expression<String> getPath(SearchCriteria criteria, Root<Student> root) {
if (criteria.getKey().equals("lastRollResult")) {
Join<Student, Result> resultsJoin = root.join("lastRoll", JoinType.LEFT);
if (!"null".equals(criteria.getValue())) {
// Handle non-null values
return resultsJoin.get("result");
} else {
// Handle null values
return builder.isNull(resultsJoin.get("result"));
}
}
return root.get(criteria.getKey());
}
更新 toPredicate 方法:确保您的 toPredicate 方法在考虑空值和非空值的情况下正确构造查询谓词。
不清楚要如何处理查询结果中的关系。如果你想返回学生数据而不管相关实体是否存在,我认为你应该尝试使用左连接:
Join results = root.join("lastRoll", JoinType.LEFT);
return results.get("result");